回到s3c_adc_probe函数:339行,设置预分频系统为49。341行,取得ADC中断号。348行,申请中断,注册ADC中断处理函数为s3c_adc_irq。354行,取得ADC时钟。361行,取得ADC I/O内存。368行,使用ioremap得到I/O内存对应的虚拟地址。375行,使能ADC时钟。377 - 382行,设置使用预分频及预分频系统。至此,ADC模块的初始化就完成了。下面我们看客户注册ADC服务的接口函数s3c_adc_register,代码如下:
207struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, 208 void (*select)(struct s3c_adc_client *client, 209 unsigned int selected), 210 void (*conv)(struct s3c_adc_client *client, 211 unsigned d0, unsigned d1, 212 unsigned *samples_left), 213 unsigned int is_ts) 214{ 215 struct s3c_adc_client *client; 216 217 WARN_ON(!pdev); 218 219 if (!select) 220 select = s3c_adc_default_select; 221 222 if (!pdev) 223 return ERR_PTR(-EINVAL); 224 225 client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL); 226 if (!client) { 227 dev_err(&pdev->dev, "no memory for adc client\n"); 228 return ERR_PTR(-ENOMEM); 229 } 230 231 client->pdev = pdev; 232 client->is_ts = is_ts; 233 client->select_cb = select; 234 client->convert_cb = conv; 235 236 return client; 237}
219 - 220行,如果没有指定select回调函数,则使用默认的回调函数s3c_adc_default_select,这个函数的实现没有做任何事情,是个空函数。由这句话可以看出,select回调函数是必须定义的,自己不定义也要使用默认的。而convert回调函数则不是必须定义的。225 - 234行,为client分配空间,并初始化相关成员。236行,返回client。当客户要读取AD转换结果时,可调用s3c_adc_read函数,其定义如下:
175int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch) 176{ 177 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); 178 int ret; 179 180 client->convert_cb = s3c_convert_done; 181 client->wait = &wake; 182 client->result = -1; 183 184 ret = s3c_adc_start(client, ch, 1); 185 if (ret < 0) 186 goto err; 187 188 ret = wait_event_timeout(wake, client->result >= 0, HZ / 2); 189 if (client->result < 0) { 190 ret = -ETIMEDOUT; 191 goto err; 192 } 193 194 client->convert_cb = NULL; 195 return client->result; 196 197err: 198 return ret; 199}
175行,第二个参数ch代表要读ADC控制器的哪个通道。177行,定义等待队列头。180行,指定convert回调函数是s3c_convert_done,该函数我们在后面分析。184行,调用s3c_adc_start函数,该函数我们在后面分析,第二个参数代表使用的ADC通道,第三个参数指定采样次数,这里可以看出,使用s3c_adc_read,采样次数均为1。188行,调用wait_event_timeout在等待队列wake上休眠,休眠条件是 client->result >= 0,最长休眠时间为HZ/2。client��convert回调函数s3c_convert_done定义如下:
168static void s3c_convert_done(struct s3c_adc_client *client, 169 unsigned v, unsigned u, unsigned *left) 170{ 171 client->result = v; 172 wake_up(client->wait); 173}
171行,将第二个参数(data0)赋值给client->result。172行,唤醒等待队列中的休眠进程。