| /* |
| * SPI OF support routines |
| * Copyright (C) 2008 Secret Lab Technologies Ltd. |
| * |
| * Support routines for deriving SPI device attachments from the device |
| * tree. |
| */ |
| |
| #include <linux/of.h> |
| #include <linux/device.h> |
| #include <linux/spi/spi.h> |
| #include <linux/of_spi.h> |
| |
| /** |
| * of_register_spi_devices - Register child devices onto the SPI bus |
| * @master: Pointer to spi_master device |
| * @np: parent node of SPI device nodes |
| * |
| * Registers an spi_device for each child node of 'np' which has a 'reg' |
| * property. |
| */ |
| void of_register_spi_devices(struct spi_master *master, struct device_node *np) |
| { |
| struct spi_device *spi; |
| struct device_node *nc; |
| const u32 *prop; |
| int rc; |
| int len; |
| |
| for_each_child_of_node(np, nc) { |
| /* Alloc an spi_device */ |
| spi = spi_alloc_device(master); |
| if (!spi) { |
| dev_err(&master->dev, "spi_device alloc error for %s\n", |
| nc->full_name); |
| spi_dev_put(spi); |
| continue; |
| } |
| |
| /* Select device driver */ |
| if (of_modalias_node(nc, spi->modalias, |
| sizeof(spi->modalias)) < 0) { |
| dev_err(&master->dev, "cannot find modalias for %s\n", |
| nc->full_name); |
| spi_dev_put(spi); |
| continue; |
| } |
| |
| /* Device address */ |
| prop = of_get_property(nc, "reg", &len); |
| if (!prop || len < sizeof(*prop)) { |
| dev_err(&master->dev, "%s has no 'reg' property\n", |
| nc->full_name); |
| spi_dev_put(spi); |
| continue; |
| } |
| spi->chip_select = *prop; |
| |
| /* Mode (clock phase/polarity/etc.) */ |
| if (of_find_property(nc, "spi-cpha", NULL)) |
| spi->mode |= SPI_CPHA; |
| if (of_find_property(nc, "spi-cpol", NULL)) |
| spi->mode |= SPI_CPOL; |
| if (of_find_property(nc, "spi-cs-high", NULL)) |
| spi->mode |= SPI_CS_HIGH; |
| |
| /* Device speed */ |
| prop = of_get_property(nc, "spi-max-frequency", &len); |
| if (!prop || len < sizeof(*prop)) { |
| dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n", |
| nc->full_name); |
| spi_dev_put(spi); |
| continue; |
| } |
| spi->max_speed_hz = *prop; |
| |
| /* IRQ */ |
| spi->irq = irq_of_parse_and_map(nc, 0); |
| |
| /* Store a pointer to the node in the device structure */ |
| of_node_get(nc); |
| spi->dev.archdata.of_node = nc; |
| |
| /* Register the new device */ |
| request_module(spi->modalias); |
| rc = spi_add_device(spi); |
| if (rc) { |
| dev_err(&master->dev, "spi_device register error %s\n", |
| nc->full_name); |
| spi_dev_put(spi); |
| } |
| |
| } |
| } |
| EXPORT_SYMBOL(of_register_spi_devices); |