Linux下SPI驱动分析(3)
2011-03-05 15:01
369 查看
接下去看spi.c
------------------------------------------------
下回看SPI主机注册、删除方法,休息~
特殊的板级相关设备添加方法 /* 神奇的分割线 */ 190/*-------------------------------------------------------------------------*/ 191 192/* SPI devices should normally not be created by SPI device drivers; that 193 * would make them board-specific. Similarly with SPI master drivers. 194 * Device registration normally goes into like arch/.../mach.../board-YYY.c 195 * with other readonly (flashable) information about mainboard devices. 196 */ 197 /* 板级相关信息链表 */ 198struct boardinfo { 199 struct list_head list; 200 struct spi_board_info board_info; 201}; 202 203static LIST_HEAD(board_list); 204static LIST_HEAD(spi_master_list); 206/* 207 * Used to protect add/del opertion for board_info list and 208 * spi_master list, and their matching process 209 */ /* 链表操作锁 */ 210static DEFINE_MUTEX(board_lock); 211 212/** 213 * spi_alloc_device - Allocate a new SPI device 214 * @master: Controller to which device is connected 215 * Context: can sleep 216 * 217 * Allows a driver to allocate and initialize a spi_device without 218 * registering it immediately. This allows a driver to directly 219 * fill the spi_device with device parameters before calling 220 * spi_add_device() on it. 221 * 222 * Caller is responsible to call spi_add_device() on the returned 223 * spi_device structure to add it to the SPI master. If the caller 224 * needs to discard the spi_device without adding it, then it should 225 * call spi_dev_put() on it. 226 * 227 * Returns a pointer to the new device, or NULL. 228 */ /* 为申请SPI设备结构体空间而不注册设备,必须调用spi_add_device,如要丢弃这个设备 * 则必须调用spi_dev_put */ 229struct spi_device *spi_alloc_device(struct spi_master *master) 230{ 231 struct spi_device *spi; 232 struct device *dev = master->dev.parent; 233 /* 增加设备引用次数,相反操作spi_master_put */ 234 if (!spi_master_get(master)) 235 return NULL; 236 /* 申请内核空间内存 */ 237 spi = kzalloc(sizeof *spi, GFP_KERNEL); 238 if (!spi) { 239 dev_err(dev, "cannot alloc spi_device/n"); 240 spi_master_put(master); 241 return NULL; 242 } 243 /* SPI主机控制结构体 */ 244 spi->master = master; /* 设备 */ 245 spi->dev.parent = dev; /* 总线 */ 246 spi->dev.bus = &spi_bus_type; /* 删除方法 */ 247 spi->dev.release = spidev_release; /* 设备初始化 * 初始化kobject,dma池链表,设备互斥锁,自旋锁,设备对象的电源相关部分 * src/drivers/base/core.c */ 248 device_initialize(&spi->dev); /* 返回spi设备结构体指针 */ 249 return spi; 250} 251EXPORT_SYMBOL_GPL(spi_alloc_device); 252 253/** 254 * spi_add_device - Add spi_device allocated with spi_alloc_device 255 * @spi: spi_device to register 256 * 257 * Companion function to spi_alloc_device. Devices allocated with 258 * spi_alloc_device can be added onto the spi bus with this function. 259 * 260 * Returns 0 on success; negative errno on failure 261 */ /* 与spi_alloc_device配合使用,将设备结构体添加到SPI总线 */ 262int spi_add_device(struct spi_device *spi) 263{ 264 static DEFINE_MUTEX(spi_add_lock); 265 struct device *dev = spi->master->dev.parent; 266 struct device *d; 267 int status; 268 269 /* Chipselects are numbered 0..max; validate. */ /* 设备片选编号比SPI主控制器的片选大,出错 */ 270 if (spi->chip_select >= spi->master->num_chipselect) { 271 dev_err(dev, "cs%d >= max %d/n", 272 spi->chip_select, 273 spi->master->num_chipselect); 274 return -EINVAL; 275 } 276 277 /* Set the bus ID string */ /* 设置设备名称,调用kobject的设置设备名称参数方法 */ 278 dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev), 279 spi->chip_select); 280 281 282 /* We need to make sure there's no other device with this 283 * chipselect **BEFORE** we call setup(), else we'll trash 284 * its configuration. Lock against concurrent add() calls. 285 */ /* 互斥锁,保证设置时,没有其他设备用这个片选,防止并发添加add() */ 286 mutex_lock(&spi_add_lock); 287 /* 按照名称字符查找设备结构体,设备名称由dev_name查找kobject返回 * 能够找到说明设备已经在用 */ 288 d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev)); 289 if (d != NULL) { 290 dev_err(dev, "chipselect %d already in use/n", 291 spi->chip_select); 292 put_device(d); 293 status = -EBUSY; 294 goto done; 295 } 296 297 /* Drivers may modify this initial i/o setup, but will 298 * normally rely on the device being setup. Devices 299 * using SPI_CS_HIGH can't coexist well otherwise... 300 */ /* /* 设置SPI模式和时钟频率 * 驱动可以初始化IO,当设备被设置的时候 * 取消片选没有用 * 详细见后面驱动核心方法spi_setup解析 */ 301 status = spi_setup(spi); 302 if (status < 0) { 303 dev_err(dev, "can't setup %s, status %d/n", 304 dev_name(&spi->dev), status); 305 goto done; 306 } 307 308 /* Device may be bound to an active driver when this returns */ /* 将设备添加到驱动层次结构,添加到kobject层次结构,添加到其他子系统 */ 309 status = device_add(&spi->dev); 310 if (status < 0) 311 dev_err(dev, "can't add %s, status %d/n", 312 dev_name(&spi->dev), status); 313 else 314 dev_dbg(dev, "registered child %s/n", dev_name(&spi->dev)); 315 316done: 317 mutex_unlock(&spi_add_lock); 318 return status; 319} 320EXPORT_SYMBOL_GPL(spi_add_device); 321 322/** 323 * spi_new_device - instantiate one new SPI device 324 * @master: Controller to which device is connected 325 * @chip: Describes the SPI device 326 * Context: can sleep 327 * 328 * On typical mainboards, this is purely internal; and it's not needed 329 * after board init creates the hard-wired devices. Some development 330 * platforms may not be able to use spi_register_board_info though, and 331 * this is exported so that for example a USB or parport based adapter 332 * driver could add devices (which it would learn about out-of-band). 333 * 334 * Returns the new device, or NULL. 335 */ /* 有些开发平台可能不能通过spi_register_board_info添加设备 * 这个用来让一些比如基于USB适配的驱动添加设备 */ 336struct spi_device *spi_new_device(struct spi_master *master, 337 struct spi_board_info *chip) 338{ 339 struct spi_device *proxy; 340 int status; 341 342 /* NOTE: caller did any chip->bus_num checks necessary. 343 * 344 * Also, unless we change the return value convention to use 345 * error-or-pointer (not NULL-or-pointer), troubleshootability 346 * suggests syslogged diagnostics are best here (ugh). 347 */ 348 /* 分配设备结构体内存空间,并初始化 */ 349 proxy = spi_alloc_device(master); 350 if (!proxy) 351 return NULL; 352 353 WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias)); 354 355 proxy->chip_select = chip->chip_select; 356 proxy->max_speed_hz = chip->max_speed_hz; 357 proxy->mode = chip->mode; 358 proxy->irq = chip->irq; 359 strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias)); 360 proxy->dev.platform_data = (void *) chip->platform_data; 361 proxy->controller_data = chip->controller_data; 362 proxy->controller_state = NULL; 363 /* 添加设备 */ 364 status = spi_add_device(proxy); 365 if (status < 0) { 366 spi_dev_put(proxy); 367 return NULL; 368 } 369 370 return proxy; 371} 372EXPORT_SYMBOL_GPL(spi_new_device); 373 /* 使用主控制类和板级信息匹配则添加一个新设备 */ 374static void spi_match_master_to_boardinfo(struct spi_master *master, 375 struct spi_board_info *bi) 376{ 377 struct spi_device *dev; 378 379 if (master->bus_num != bi->bus_num) 380 return; 381 382 dev = spi_new_device(master, bi); 383 if (!dev) 384 dev_err(master->dev.parent, "can't create new device for %s/n", 385 bi->modalias); 386} 387 388/** 389 * spi_register_board_info - register SPI devices for a given board 390 * @info: array of chip descriptors 391 * @n: how many descriptors are provided 392 * Context: can sleep 393 * 394 * Board-specific early init code calls this (probably during arch_initcall) 395 * with segments of the SPI device table. Any device nodes are created later, 396 * after the relevant parent SPI controller (bus_num) is defined. We keep 397 * this table of devices forever, so that reloading a controller driver will 398 * not make Linux forget about these hard-wired devices. 399 * 400 * Other code can also call this, e.g. a particular add-on board might provide 401 * SPI devices through its expansion connector, so code initializing that board 402 * would naturally declare its SPI devices. 403 * 404 * The board info passed can safely be __initdata ... but be careful of 405 * any embedded pointers (platform_data, etc), they're copied as-is. 406 */ /* 使用一系列板级描述信息初始化设备 */ 407int __init 408spi_register_board_info(struct spi_board_info const *info, unsigned n) 409{ 410 struct boardinfo *bi; 411 int i; 412 413 bi = kzalloc(n * sizeof(*bi), GFP_KERNEL); 414 if (!bi) 415 return -ENOMEM; 416 417 for (i = 0; i < n; i++, bi++, info++) { 418 struct spi_master *master; 419 420 memcpy(&bi->board_info, info, sizeof(*info)); 421 mutex_lock(&board_lock); /* 添加到板级描述符链表 */ 422 list_add_tail(&bi->list, &board_list); /* 将主机控制类链表所有的节点匹配板级信息的设备初始化 */ 423 list_for_each_entry(master, &spi_master_list, list) 424 spi_match_master_to_boardinfo(master, &bi->board_info); 425 mutex_unlock(&board_lock); 426 } 427 428 return 0; 429} 430 431/*-------------------------------------------------------------------------*/
------------------------------------------------
下回看SPI主机注册、删除方法,休息~
相关文章推荐
- Linux下SPI驱动分析
- Linux驱动修炼之道-SPI驱动框架源码分析(下)
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
- Linux驱动修炼之道-SPI驱动框架源码分析(中)
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
- Linux驱动修炼之道-SPI驱动框架源码分析(中-续)
- Linux下SPI驱动分析
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
- Linux下SPI驱动分析
- Linux驱动修炼之道-SPI驱动框架源码分析(中)
- Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)
- Linux驱动修炼之道-SPI驱动框架源码分析(下-续)
- linux下spi驱动分析
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
- Linux驱动修炼之道-SPI驱动框架源码分析(中)
- Linux驱动修炼之道-SPI驱动框架源码分析(下)
- Linux驱动修炼之道-SPI驱动框架源码分析(下)
- Linux驱动修炼之道-SPI驱动框架源码分析(中)