summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c65
1 files changed, 61 insertions, 4 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a7fe10cba0..44040e5f62 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -15,10 +15,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
*
*/
@@ -27,6 +23,8 @@
#include <xfuncs.h>
#include <malloc.h>
#include <errno.h>
+#include <init.h>
+#include <of.h>
/* SPI devices should normally not be created by SPI device drivers; that
* would make them board-specific. Similarly with SPI master drivers.
@@ -77,10 +75,12 @@ struct spi_device *spi_new_device(struct spi_master *master,
proxy->mode = chip->mode;
proxy->bits_per_word = chip->bits_per_word ? chip->bits_per_word : 8;
proxy->dev.platform_data = chip->platform_data;
+ proxy->dev.bus = &spi_bus;
strcpy(proxy->dev.name, chip->name);
/* allocate a free id for this chip */
proxy->dev.id = DEVICE_ID_DYNAMIC;
proxy->dev.type_data = proxy;
+ proxy->dev.device_node = chip->device_node;
dev_add_child(master->dev, &proxy->dev);
/* drivers may modify this initial i/o setup */
@@ -100,6 +100,27 @@ fail:
}
EXPORT_SYMBOL(spi_new_device);
+#ifdef CONFIG_OFDEVICE
+void spi_of_register_slaves(struct spi_master *master, struct device_node *node)
+{
+ struct device_node *n;
+ struct spi_board_info chip;
+ struct property *reg;
+
+ device_node_for_nach_child(node, n) {
+ chip.name = n->name;
+ chip.bus_num = master->bus_num;
+ chip.max_speed_hz = 300000; /* FIXME */
+ reg = of_find_property(n, "reg");
+ if (!reg)
+ continue;
+ chip.chip_select = of_read_number(reg->value, 1);
+ chip.device_node = n;
+ spi_register_board_info(&chip, 1);
+ }
+}
+#endif
+
/**
* spi_register_board_info - register SPI devices for a given board
* @info: array of chip descriptors
@@ -154,6 +175,8 @@ static void scan_boardinfo(struct spi_master *master)
}
}
+static LIST_HEAD(spi_master_list);
+
/**
* spi_register_master - register SPI master controller
* @master: initialized master, originally from spi_alloc_master()
@@ -186,6 +209,8 @@ int spi_register_master(struct spi_master *master)
if (master->num_chipselect == 0)
return -EINVAL;
+ list_add_tail(&master->list, &spi_master_list);
+
/* populate children from any spi device tables */
scan_boardinfo(master);
status = 0;
@@ -240,3 +265,35 @@ int spi_write_then_read(struct spi_device *spi,
return status;
}
EXPORT_SYMBOL(spi_write_then_read);
+
+static int spi_match(struct device_d *dev, struct driver_d *drv)
+{
+ if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node &&
+ drv->of_compatible)
+ return of_match(dev, drv);
+
+ return strcmp(dev->name, drv->name) ? -1 : 0;
+}
+
+static int spi_probe(struct device_d *dev)
+{
+ return dev->driver->probe(dev);
+}
+
+static void spi_remove(struct device_d *dev)
+{
+ dev->driver->remove(dev);
+}
+
+struct bus_type spi_bus = {
+ .name = "spi",
+ .match = spi_match,
+ .probe = spi_probe,
+ .remove = spi_remove,
+};
+
+static int spi_bus_init(void)
+{
+ return bus_register(&spi_bus);
+}
+pure_initcall(spi_bus_init);