| 138 | | /* OK, this is no detection. I know. It will do for now, though. */ |
|---|
| 139 | | |
|---|
| 140 | | /* Set err only if a global error would make registering other clients |
|---|
| 141 | | impossible too (like out-of-memory). */ |
|---|
| 142 | | |
|---|
| 143 | | /* ICS and PLL clock chips seem to all be at 0x69. |
|---|
| 144 | | Don't know what is out there at 0x6A, don't scan that yet. */ |
|---|
| 145 | | |
|---|
| 146 | | for (address = 0x69; (!err) && (address <= 0x69); address++) { |
|---|
| 147 | | |
|---|
| 148 | | /* Later on, we will keep a list of registered addresses for each |
|---|
| 149 | | adapter, and check whether they are used here */ |
|---|
| 150 | | |
|---|
| 151 | | /* these chips only support block transfers so use that for detection */ |
|---|
| 152 | | if (i2c_smbus_read_block_data |
|---|
| 153 | | (adapter, address, 0x00, tempdata) < 0) { |
|---|
| 154 | | #ifdef DEBUG |
|---|
| 155 | | printk("icspll.o: No icspll found at: 0x%X\n", |
|---|
| 156 | | address); |
|---|
| 157 | | #endif |
|---|
| 158 | | continue; |
|---|
| 159 | | } |
|---|
| 160 | | |
|---|
| 161 | | /* Real detection code goes here */ |
|---|
| 162 | | |
|---|
| 163 | | /* Allocate space for a new client structure */ |
|---|
| 164 | | if (!(new_client = kmalloc(sizeof(struct i2c_client) + |
|---|
| 165 | | sizeof(struct icspll_data), |
|---|
| 166 | | GFP_KERNEL))) { |
|---|
| 167 | | err = -ENOMEM; |
|---|
| 168 | | continue; |
|---|
| 169 | | } |
|---|
| 170 | | |
|---|
| 171 | | /* Fill the new client structure with data */ |
|---|
| 172 | | data = (struct icspll_data *) (new_client + 1); |
|---|
| 173 | | new_client->data = data; |
|---|
| 174 | | new_client->id = icspll_id++; |
|---|
| 175 | | new_client->addr = address; |
|---|
| 176 | | new_client->adapter = adapter; |
|---|
| 177 | | new_client->driver = &icspll_driver; |
|---|
| 178 | | new_client->flags = 0; |
|---|
| 179 | | strcpy(new_client->name, "ICSPLL chip"); |
|---|
| 180 | | data->valid = 0; |
|---|
| 181 | | init_MUTEX(&data->update_lock); |
|---|
| 182 | | /* fill data structure so unknown registers are 0xFF */ |
|---|
| 183 | | data->data[0] = ICSPLL_SIZE; |
|---|
| 184 | | for (i = 1; i <= ICSPLL_SIZE; i++) |
|---|
| 185 | | data->data[i] = 0xFF; |
|---|
| 186 | | |
|---|
| 187 | | /* Tell i2c-core a new client has arrived */ |
|---|
| 188 | | if ((err = i2c_attach_client(new_client))) |
|---|
| 189 | | goto ERROR2; |
|---|
| 190 | | |
|---|
| 191 | | /* Register a new directory entry with module sensors */ |
|---|
| 192 | | if ((err = sensors_register_entry(new_client, "icspll", |
|---|
| 193 | | icspll_dir_table_template |
|---|
| 194 | | THIS_MODULE)) < 0) |
|---|
| 195 | | goto ERROR3; |
|---|
| 196 | | data->sysctl_id = err; |
|---|
| 197 | | err = 0; |
|---|
| 198 | | |
|---|
| 199 | | continue; |
|---|
| 200 | | /* OK, this is not exactly good programming practice, usually. But it is |
|---|
| 201 | | very code-efficient in this case. */ |
|---|
| 202 | | |
|---|
| 203 | | ERROR3: |
|---|
| 204 | | i2c_detach_client(new_client); |
|---|
| 205 | | ERROR2: |
|---|
| 206 | | ERROR1: |
|---|
| 207 | | kfree(new_client); |
|---|
| 208 | | } |
|---|
| | 154 | if (address != ADDRESS) |
|---|
| | 155 | return 0; |
|---|
| | 156 | |
|---|
| | 157 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | |
|---|
| | 158 | I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { |
|---|
| | 159 | printk("icspll.o: Adapter does not support SMBus writes and Block reads\n"); |
|---|
| | 160 | goto ERROR0; |
|---|
| | 161 | } |
|---|
| | 162 | |
|---|
| | 163 | /* Allocate space for a new client structure */ |
|---|
| | 164 | if (!(new_client = kmalloc(sizeof(struct i2c_client) + |
|---|
| | 165 | sizeof(struct icspll_data), |
|---|
| | 166 | GFP_KERNEL))) { |
|---|
| | 167 | err = -ENOMEM; |
|---|
| | 168 | goto ERROR0; |
|---|
| | 169 | } |
|---|
| | 170 | |
|---|
| | 171 | /* Fill the new client structure with data */ |
|---|
| | 172 | data = (struct icspll_data *) (new_client + 1); |
|---|
| | 173 | new_client->data = data; |
|---|
| | 174 | new_client->id = icspll_id++; |
|---|
| | 175 | new_client->addr = address; |
|---|
| | 176 | new_client->adapter = adapter; |
|---|
| | 177 | new_client->driver = &icspll_driver; |
|---|
| | 178 | new_client->flags = 0; |
|---|
| | 179 | strcpy(new_client->name, "Clock chip"); |
|---|
| | 180 | data->valid = 0; |
|---|
| | 181 | init_MUTEX(&data->update_lock); |
|---|
| | 182 | |
|---|
| | 183 | /* use write-quick for detection */ |
|---|
| | 184 | if (i2c_smbus_write_quick(new_client, 0x00) < 0) { |
|---|
| | 185 | printk("icspll.o: No device found at 0x%X\n", address); |
|---|
| | 186 | goto ERROR1; |
|---|
| | 187 | } |
|---|
| | 188 | |
|---|
| | 189 | /* fill data structure so unknown registers are 0xFF */ |
|---|
| | 190 | data->data[0] = ICSPLL_SIZE; |
|---|
| | 191 | for (i = 1; i <= ICSPLL_SIZE; i++) |
|---|
| | 192 | data->data[i] = 0xFF; |
|---|
| | 193 | |
|---|
| | 194 | /* Tell i2c-core a new client has arrived */ |
|---|
| | 195 | if ((err = i2c_attach_client(new_client))) |
|---|
| | 196 | goto ERROR2; |
|---|
| | 197 | |
|---|
| | 198 | /* Register a new directory entry with module sensors */ |
|---|
| | 199 | if ((err = sensors_register_entry(new_client, "icspll", |
|---|
| | 200 | icspll_dir_table_template, |
|---|
| | 201 | THIS_MODULE)) < 0) |
|---|
| | 202 | goto ERROR3; |
|---|
| | 203 | data->sysctl_id = err; |
|---|
| | 204 | err = 0; |
|---|
| | 205 | |
|---|
| | 206 | ERROR3: |
|---|
| | 207 | i2c_detach_client(new_client); |
|---|
| | 208 | ERROR2: |
|---|
| | 209 | ERROR1: |
|---|
| | 210 | kfree(new_client); |
|---|
| | 211 | ERROR0: |
|---|