aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-12-06 11:06:17 -0500
committerJean Delvare <khali@linux-fr.org>2009-12-06 11:06:17 -0500
commit02864d58ce102804b148c92e44726d9571d65d1e (patch)
treea2f94e0dfa1e07e2cbaeec55187afe46b1bef109 /drivers/i2c
parent6f7e549f873e9ff10a4a27241db568bf7988ee0c (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.c85
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;