Documente Academic
Documente Profesional
Documente Cultură
Best-Practice Guidelines
2
Best Practices?!
General theories:
Not if, but when it breaks
What will I need at that time?
What did I wish I had last time?
But:
We cant unduly burden the nominal cases
We must not increase the risk of defects!
3
Best Practices?!
4
Best Practices?!
General themes:
Never tell Linux how, only what
Express our needs, make Linux address them
Fully embrace device model vs. interface paradigm
5
Best Practices?!
More specically:
Full visibility into hardware state
No platform-specic code in drivers
No driver code in interface methods
No interface code in driver methods
No redundant code anywhere
6
Best Practices?!
7
Best Practices?!
Peripheral controls:
If it has one, I want to see it
... from the command line
8
Best Practices?!
Choices, choices...
I2C?
SPI?
Platform?
9
Register Accessors
Register Accessors
1 static inline
2 void __raw_writel(
3 u32 b, volatile void *addr);
4
5 s32 i2c_smbus_write_byte(
6 const struct i2c_client *client,
7 u8 value);
8
9 static inline int
10 spi_write(struct spi_device *spi,
11 const void *buf, size_t len);
11
Register Accessors
12
Register Accessors
13
Register Accessors
1 enum { /* bma250 */
2 BMA_REG_CHIP_ID = 0,
3 BMA_REG_VERSION = 1,
4
5 BMA_REG_X_AXIS_LSB = 2,
6 BMA_REG_X_AXIS_MSB = 3,
7 BMA_REG_Y_AXIS_LSB = 4,
8 BMA_REG_Y_AXIS_MSB = 5,
9 ...
10 BMA_REG_CTRL1 = 16,
11 ...
12 };
14
Register Accessors
1 enum {
2 BMA_REG_CHIP_ID = 0,
3 BMA_REG_CHIP_ID__reserved = 0,
4 ...
5 BMA_REG_X_AXIS_LSB = 2,
6 BMA_REG_X_AXIS_LSB__reserved = 0x3e,
7 ...
8 BMA_REG_CTRL1 = 16,
9 BMA_REG_CTRL1__reserved = 0x80,
10 BMA_REG_CTRL1__RATE = 0x18,
11 ...
12 };
15
Register Accessors
16
Register Accessors
Ouch!
Tedious, redundant, error-prone
17
Basic Reads and Writes
Basic Reads and Writes
1 #define BMA_REG_READ(_name) \
2 int __bma_reg_read_##_name(struct bma *bma) \
3 { \
4 int ret; \
5 ret = __bma_reg_read(bma, BMA_REG_##_name); \
6 if (ret < 0) return ret; \
7 ret &= ~BMA_REG_##_name ## __reserved; \
8 dev_dbg(&bma->client->dev, %s: %02x\n, \
9 __func__, ret); \
10 return ret; \
11 }
19
Basic Reads and Writes
1 ...
2 BMA_REG_READ(X_AXIS_LSB);
3 BMA_REG_READ(Y_AXIS_LSB);
4 BMA_REG_READ(Z_AXIS_LSB);
5 ...
20
Basic Reads and Writes
1 ...
2 id = __bma_reg_read_CHIP_ID(bma);
3 ...
4 x_axis_lsb = __bma_reg_read_X_AXIS_LSB(bma);
5 ...
21
Basic Reads and Writes
1 #define BMA_REG_WRITE(_name) \
2 int __bma_reg_write_##_name( \
3 struct bma *bma, int v) \
4 { \
5 dev_dbg(&bma->client->dev, \
6 %s: %02x\n, __func__, v); \
7 v &= ~BMA_REG_##_name ## __reserved; \
8 return __bma_reg_write(bma, \
9 BMA_REG_##_name, v); \
10 }
22
Basic Reads and Writes
23
Basic Reads and Writes
24
Bit Fields
Bit Fields
26
Bit Fields
27
Bit Fields
28
Bit Fields
29
Bit Fields
32
Write-Only Registers
1 #define BMA_REG_WRITE(_name) \
2 int __bma_reg_write_##_name( \
3 struct bma *bma, int v) \
4 { \
5 int ret; \
6 v &= ~BMA_REG_##_name ## __reserved; \
7 ret = __bma_reg_write( \
8 bma, BMA_REG_##_name, v); \
9 if (ret < 0) return ret; \
10 switch (BMA_REG_##_name) { \
11 case BMA_REG_RANGE: bma->RANGE = v; break; \
12 case BMA_REG_RESET: usleep(4000); break; \
13 } \
14 return 0; \
15 }
33
Write-Only Registers
1 #define BMA_REG_READ(_name) \
2 int __bma_reg_read_##_name(struct bma *bma) \
3 { \
4 int ret = __bma_reg_read( \
5 bma, BMA_REG_##_name); \
6 if (ret < 0) return ret; \
7 ret &= ~BMA_REG_##_name ## __reserved; \
8 switch (BMA_REG_##_name) { \
9 case BMA_REG_RANGE: bma->RANGE = ret; break; \
10 } \
11 return ret; \
12 }
34
Write-Only Registers
35
Write-Only Registers
1 #define BMA_REG_READ(_name) \
2 int __bma_reg_read_##_name(struct bma *bma) \
3 { \
4 int ret; \
5 switch (BMA_REG_##_name) { \
6 case BMA_REG_RANGE: return bma->RANGE; \
7 } \
8 ret = __bma_reg_read(bma, BMA_REG_##_name); \
9 if (ret < 0) return ret; \
10 ret &= ~BMA_REG_##_name ## __reserved; \
11 return ret; \
12 }
36
Write-Only Registers
1 ...
2 static int bma_do_reset(struct bma *bma)
3 {
4 int ret;
5
6 __bma_lock(bma);
7 ret = __bma_reg_write_RESET(bma);
8 ...
9 ret = __bma_reg_write_RANGE(bma, bma->RANGE);
10 ...
11 __bma_unlock(bma);
12 }
13 ...
37
Write-Only Registers
1 #define BMA_REG_READWRITE(name) \
2 BMA_REG_READ(name) \
3 BMA_REG_WRITE(name)
4 ...
5 BMA_REG_READ(CHIP_ID)
6 BMA_REG_READ(X_AXIS_LSB)
7 BMA_REG_WRITE(RANGE)
8 BMA_REG_READWRITE(RESET)
9 ...
38
Control Register Attributes
Control Register Attributes
1 root@device:# cd /sys/bus/i2c/devices
2 root@device:# ls -l 2-0070
3 ...
4 -r--r--r-- 1 root root 4096 Jun 16 18:04 CHIP_ID
5 -r--r--r-- 1 root root 4096 Jun 16 18:04 VERSION
6 -r--r--r-- 1 root root 4096 Jun 16 18:04 X_AXIS_LSB
7 -r--r--r-- 1 root root 4096 Jun 16 18:04 Y_AXIS_LSB
8 ...
9 -rw-r--r-- 1 root root 4096 Jun 16 18:04 CTRL1
10 ...
11 root@device:# cat .../X_AXIS_LSB
12 127
13 root@device:# echo 89 > .../CTRL1
40
Control Register Attributes
1 ...
2 enum {
3 BMA_REG_CHIP_ID = 0,
4 BMA_REG_CHIP_ID__reserved = 0,
5 ...
6 BMA_REG_X_AXIS_LSB = 2,
7 BMA_REG_X_AXIS_LSB__reserved = 0x3e,
8 ...
9 };
41
Control Register Attributes
42
Control Register Attributes
43
Control Register Attributes
44
Control Register Attributes
1 #define BMA_REG_READ(_name) \
2 int __bma_reg_read_##_name(struct bma *bma) \
3 { \
4 int ret = __bma_reg_read( \
5 bma, BMA_REG_##_name); \
6 if (ret < 0) return ret; \
7 ret &= ~BMA_REG_##_name ## __reserved; \
8 dev_dbg(&bma->client->dev, \
9 %s: %02x\n, __func__, ret); \
10 return ret; \
11 }
45
Control Register Attributes
46
Control Register Attributes
1 #define BMA_REG_ATTR_STORE(_name) \
2 ssize_t bma_store_##_name(struct device *dev, \
3 struct device_attribute *attr, \
4 const char *buf, size_t len) \
5 { \
6 struct bma *bma = dev_get_drvdata(dev); \
7 int ret; \
8 unsigned long v; \
9 ret = strict_strtoul(buf, 16, &v); \
10 if (ret) return ret; \
11 ...
47
Control Register Attributes
1 #define BMA_REG_ATTR_STORE(_name) \
2 ... \
3 __bma_lock(bma); \
4 switch (BMA_REG_##_name) { \
5 case BMA_REG_POWER: \
6 ret = __bma_reg_write_POWER(bma, v); \
7 break; \
8 case BMA_REG_RESET: \
9 ret = __bma_reg_write_RESET(bma, v); \
10 usleep(4000); /* ! */ \
11 break; \
12 ...
48
Control Register Attributes
1 #define BMA_REG_ATTR_STORE(_name) \
2 ... \
3 default: \
4 ret = __bma_reg_write_##_name(bma, v); \
5 break; \
6 } \
7 __bma_unlock(bma); \
8 return (ret < 0) ? ret : len; \
9 }
49
Control Register Attributes
50
Control Register Attributes
51
Control Register Attributes
1 #define BMA_REG(_name) \
2 BMA_REG_READ(_name) \
3 BMA_REG_ATTR_SHOW(_name) \
4 DEVICE_ATTR(_name, S_IRUGO, bma_show_##_name, NULL);
5
6 ...
7 BMA_REG(BMA_REG_X_AXIS_LSB);
8 BMA_REG(BMA_REG_Y_AXIS_LSB);
9 ...
52
Control Register Attributes
1 #define BMA_REG_READWRITE(_name) \
2 BMA_REG_READ(_name) \
3 BMA_REG_WRITE(_name) \
4 BMA_REG_ATTR_SHOW(_name) \
5 BMA_REG_ATTR_STORE(_name) \
6 DEVICE_ATTR(_name, S_IRUGO | S_IWUSR, \
7 bma_show_##_name, bma_store_##_name);
8
9 ...
10 BMA_REG_READWRITE(BMA_REG_POWER);
11 ...
53
Control Register Attributes
54
Control Register Attributes
55
Control Register Attributes
56
Control Register Attributes
57
Control Register Attributes
58
Access Layer Portability
Access Layer Portability
struct device_driver
... contains nothing about the underlying media
struct i2c_driver
A simple wrapper around struct device_driver
Creates a bus, and other helper abstractions
60
Access Layer Portability
struct spi_driver
Same thing!
struct platform_driver
... but I repeat myself again
61
Access Layer Portability
62
Access Layer Portability
63
Access Layer Portability
1 struct bma {
2 struct mutex m;
3 spin_lock_t s;
4 ...
5 struct device *dev;
6 struct i2c_client *i2c;
7 struct spi_device *spi;
8 ...
9 };
64
Access Layer Portability
65
Access Layer Portability
66
Access Layer Portability
1 ...
2 i2c_set_clientdata(client, bma);
3 bma->i2c = client;
4 bma->dev = &i2c->dev;
5
6 ret = bma_probe(bma);
7 if (ret)
8 kfree(bma);
9 return ret;
10 }
67
Access Layer Portability
68
Access Layer Portability
1 int module_init(void)
2 {
3 int ret;
4
5 ret = i2c_add_driver(...);
6 ...
7 ret = spi_register_driver(...);
8 ...
9 return ret;
10 }
69
Access Layer Portability
70
Devices vs. Interfaces
Devices vs. Interfaces
struct device
Represents something power-managed
Captures hierarchy, dependencies
struct file_operations
Represents... le operations!
open(), write(), etc.
mmap(), ioctl()
72
Devices vs. Interfaces
73
Eliminate Callbacks
Eliminate Callbacks
1 struct foo_board_data {
2 void (callback*)(void);
3 };
4
5 struct foo_board_data foo_board = {
6 .callback = do_something_horrible();
7 };
8
9 struct platform_device foo_device = {
10 .dev.platform_data = &foo_board,
11 };
12 ...
75
Eliminate Callbacks
76
Eliminate Callbacks
1 struct foo_board_data {
2 void (callback*)(int);
3 };
4
5 struct foo_board_data foo_board = {
6 .callback = do_gpio_enables(int on);
7 };
8
9 struct platform_device foo_device = {
10 .dev.platform_data = &foo_board,
11 };
12 ...
77
Eliminate Callbacks
78
Eliminate Callbacks
79
Eliminate Callbacks
Alternatives:
Do power management in suspend()/resume()
Do GPIO management in regulator notiers
Describe regulator consumers correctly
80
Eliminate Callbacks
Any questions?
81
Copyright
Copyright 2015, by Bill Gatliff <bgat@billgatliff.com>. All Rights Reserved. You may
not reproduce or redistribute this document without prior written consent.
82
Linux Device Drivers
Best-Practice Guidelines