diff options
author | Jean Delvare <khali@linux-fr.org> | 2009-12-06 11:06:17 -0500 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-12-06 11:06:17 -0500 |
commit | 02864d58ce102804b148c92e44726d9571d65d1e (patch) | |
tree | a2f94e0dfa1e07e2cbaeec55187afe46b1bef109 /drivers/i2c | |
parent | 6f7e549f873e9ff10a4a27241db568bf7988ee0c (diff) |
i2c-powermac: Refactor i2c_powermac_smbus_xfer
I wanted to add some error logging to the i2c-powermac driver, but
found that it was very difficult due to the way the
i2c_powermac_smbus_xfer function is organized. Refactor the code in
this function so that each low-level function is only called once.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Tested-by: Michel Daenzer <michel@daenzer.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-powermac.c | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index a74f3bab05b..dba8e387f43 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c | |||
@@ -49,48 +49,38 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, | |||
49 | int rc = 0; | 49 | int rc = 0; |
50 | int read = (read_write == I2C_SMBUS_READ); | 50 | int read = (read_write == I2C_SMBUS_READ); |
51 | int addrdir = (addr << 1) | read; | 51 | int addrdir = (addr << 1) | read; |
52 | int mode, subsize, len; | ||
53 | u32 subaddr; | ||
54 | u8 *buf; | ||
52 | u8 local[2]; | 55 | u8 local[2]; |
53 | 56 | ||
54 | rc = pmac_i2c_open(bus, 0); | 57 | if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) { |
55 | if (rc) | 58 | mode = pmac_i2c_mode_std; |
56 | return rc; | 59 | subsize = 0; |
60 | subaddr = 0; | ||
61 | } else { | ||
62 | mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub; | ||
63 | subsize = 1; | ||
64 | subaddr = command; | ||
65 | } | ||
57 | 66 | ||
58 | switch (size) { | 67 | switch (size) { |
59 | case I2C_SMBUS_QUICK: | 68 | case I2C_SMBUS_QUICK: |
60 | rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); | 69 | buf = NULL; |
61 | if (rc) | 70 | len = 0; |
62 | goto bail; | ||
63 | rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0); | ||
64 | break; | 71 | break; |
65 | case I2C_SMBUS_BYTE: | 72 | case I2C_SMBUS_BYTE: |
66 | rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); | ||
67 | if (rc) | ||
68 | goto bail; | ||
69 | rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1); | ||
70 | break; | ||
71 | case I2C_SMBUS_BYTE_DATA: | 73 | case I2C_SMBUS_BYTE_DATA: |
72 | rc = pmac_i2c_setmode(bus, read ? | 74 | buf = &data->byte; |
73 | pmac_i2c_mode_combined : | 75 | len = 1; |
74 | pmac_i2c_mode_stdsub); | ||
75 | if (rc) | ||
76 | goto bail; | ||
77 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1); | ||
78 | break; | 76 | break; |
79 | case I2C_SMBUS_WORD_DATA: | 77 | case I2C_SMBUS_WORD_DATA: |
80 | rc = pmac_i2c_setmode(bus, read ? | ||
81 | pmac_i2c_mode_combined : | ||
82 | pmac_i2c_mode_stdsub); | ||
83 | if (rc) | ||
84 | goto bail; | ||
85 | if (!read) { | 78 | if (!read) { |
86 | local[0] = data->word & 0xff; | 79 | local[0] = data->word & 0xff; |
87 | local[1] = (data->word >> 8) & 0xff; | 80 | local[1] = (data->word >> 8) & 0xff; |
88 | } | 81 | } |
89 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2); | 82 | buf = local; |
90 | if (rc == 0 && read) { | 83 | len = 2; |
91 | data->word = ((u16)local[1]) << 8; | ||
92 | data->word |= local[0]; | ||
93 | } | ||
94 | break; | 84 | break; |
95 | 85 | ||
96 | /* Note that these are broken vs. the expected smbus API where | 86 | /* Note that these are broken vs. the expected smbus API where |
@@ -105,28 +95,35 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, | |||
105 | * a repeat start/addr phase (but not stop in between) | 95 | * a repeat start/addr phase (but not stop in between) |
106 | */ | 96 | */ |
107 | case I2C_SMBUS_BLOCK_DATA: | 97 | case I2C_SMBUS_BLOCK_DATA: |
108 | rc = pmac_i2c_setmode(bus, read ? | 98 | buf = data->block; |
109 | pmac_i2c_mode_combined : | 99 | len = data->block[0] + 1; |
110 | pmac_i2c_mode_stdsub); | ||
111 | if (rc) | ||
112 | goto bail; | ||
113 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block, | ||
114 | data->block[0] + 1); | ||
115 | |||
116 | break; | 100 | break; |
117 | case I2C_SMBUS_I2C_BLOCK_DATA: | 101 | case I2C_SMBUS_I2C_BLOCK_DATA: |
118 | rc = pmac_i2c_setmode(bus, read ? | 102 | buf = &data->block[1]; |
119 | pmac_i2c_mode_combined : | 103 | len = data->block[0]; |
120 | pmac_i2c_mode_stdsub); | ||
121 | if (rc) | ||
122 | goto bail; | ||
123 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, | ||
124 | &data->block[1], data->block[0]); | ||
125 | break; | 104 | break; |
126 | 105 | ||
127 | default: | 106 | default: |
128 | rc = -EINVAL; | 107 | return -EINVAL; |
129 | } | 108 | } |
109 | |||
110 | rc = pmac_i2c_open(bus, 0); | ||
111 | if (rc) | ||
112 | return rc; | ||
113 | |||
114 | rc = pmac_i2c_setmode(bus, mode); | ||
115 | if (rc) | ||
116 | goto bail; | ||
117 | |||
118 | rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len); | ||
119 | if (rc) | ||
120 | goto bail; | ||
121 | |||
122 | if (size == I2C_SMBUS_WORD_DATA && read) { | ||
123 | data->word = ((u16)local[1]) << 8; | ||
124 | data->word |= local[0]; | ||
125 | } | ||
126 | |||
130 | bail: | 127 | bail: |
131 | pmac_i2c_close(bus); | 128 | pmac_i2c_close(bus); |
132 | return rc; | 129 | return rc; |