c - How does kernel code knows which spi bus is using? -


i modified device tree file , enable spi using 4 gpio pins, support pinmux , switch gpio spi function. in linux kernel code, how code know spi bus/pins used? example, find linux kernel driver: max1111.c, drives spi adc chip. checked code, , don't find spi bus/pins specified.

i paste max1111.c below.

/*  * max1111.c - +2.7v, low-power, multichannel, serial 8-bit adcs  *  * based on arch/arm/mach-pxa/corgi_ssp.c  *  * copyright (c) 2004-2005 richard purdie  *  * copyright (c) 2008 marvell international ltd.  *  eric miao <eric.miao@marvell.com>  *  *  program free software; can redistribute and/or modify  *  under terms of gnu general public license version 2  *  publishhed free software foundation.  */  #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/err.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/spi/spi.h> #include <linux/slab.h>  enum chips { max1110, max1111, max1112, max1113 };  #define max1111_tx_buf_size 1 #define max1111_rx_buf_size 2  /* max1111 commands */ #define max1111_ctrl_pd0      (1u << 0) #define max1111_ctrl_pd1      (1u << 1) #define max1111_ctrl_sgl      (1u << 2) #define max1111_ctrl_uni      (1u << 3) #define max1110_ctrl_sel_sh   (4) #define max1111_ctrl_sel_sh   (5)   /* note: bit 4 ignored */ #define max1111_ctrl_str      (1u << 7)  struct max1111_data {     struct spi_device   *spi;     struct device       *hwmon_dev;     struct spi_message  msg;     struct spi_transfer xfer[2];     uint8_t tx_buf[max1111_tx_buf_size];     uint8_t rx_buf[max1111_rx_buf_size];     struct mutex        drvdata_lock;     /* protect msg, xfer , buffers multiple access */     int         sel_sh;     int         lsb; };  static int max1111_read(struct device *dev, int channel) {     struct max1111_data *data = dev_get_drvdata(dev);     uint8_t v1, v2;     int err;      /* writing drvdata struct not thread safe, wait on mutex */     mutex_lock(&data->drvdata_lock);      data->tx_buf[0] = (channel << data->sel_sh) |         max1111_ctrl_pd0 | max1111_ctrl_pd1 |         max1111_ctrl_sgl | max1111_ctrl_uni | max1111_ctrl_str;      err = spi_sync(data->spi, &data->msg);     if (err < 0) {         dev_err(dev, "spi_sync failed %d\n", err);         mutex_unlock(&data->drvdata_lock);         return err;     }      v1 = data->rx_buf[0];     v2 = data->rx_buf[1];      mutex_unlock(&data->drvdata_lock);      if ((v1 & 0xc0) || (v2 & 0x3f))         return -einval;      return (v1 << 2) | (v2 >> 6); }  #ifdef config_sharpsl_pm static struct max1111_data *the_max1111;  int max1111_read_channel(int channel) {     return max1111_read(&the_max1111->spi->dev, channel); } export_symbol(max1111_read_channel); #endif  /*  * note: spi devices not have default 'name' attribute,  * used hwmon applications distinguish between  * different devices, explicitly add name attribute here.  */ static ssize_t show_name(struct device *dev,              struct device_attribute *attr, char *buf) {     return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); }  static ssize_t show_adc(struct device *dev,             struct device_attribute *attr, char *buf) {     struct max1111_data *data = dev_get_drvdata(dev);     int channel = to_sensor_dev_attr(attr)->index;     int ret;      ret = max1111_read(dev, channel);     if (ret < 0)         return ret;      /*      * assume reference voltage 2.048v or 4.096v, 8-bit      * sample. lsb weight 8mv or 16mv depending on chip type.      */     return sprintf(buf, "%d\n", ret * data->lsb); }  #define max1111_adc_attr(_id)       \     sensor_device_attr(in##_id##_input, s_irugo, show_adc, null, _id)  static device_attr(name, s_irugo, show_name, null); static max1111_adc_attr(0); static max1111_adc_attr(1); static max1111_adc_attr(2); static max1111_adc_attr(3); static max1111_adc_attr(4); static max1111_adc_attr(5); static max1111_adc_attr(6); static max1111_adc_attr(7);  static struct attribute *max1111_attributes[] = {     &dev_attr_name.attr,     &sensor_dev_attr_in0_input.dev_attr.attr,     &sensor_dev_attr_in1_input.dev_attr.attr,     &sensor_dev_attr_in2_input.dev_attr.attr,     &sensor_dev_attr_in3_input.dev_attr.attr,     null, };  static const struct attribute_group max1111_attr_group = {     .attrs  = max1111_attributes, };  static struct attribute *max1110_attributes[] = {     &sensor_dev_attr_in4_input.dev_attr.attr,     &sensor_dev_attr_in5_input.dev_attr.attr,     &sensor_dev_attr_in6_input.dev_attr.attr,     &sensor_dev_attr_in7_input.dev_attr.attr,     null, };  static const struct attribute_group max1110_attr_group = {     .attrs  = max1110_attributes, };  static int setup_transfer(struct max1111_data *data) {     struct spi_message *m;     struct spi_transfer *x;      m = &data->msg;     x = &data->xfer[0];      spi_message_init(m);      x->tx_buf = &data->tx_buf[0];     x->len = max1111_tx_buf_size;     spi_message_add_tail(x, m);      x++;     x->rx_buf = &data->rx_buf[0];     x->len = max1111_rx_buf_size;     spi_message_add_tail(x, m);      return 0; }  static int max1111_probe(struct spi_device *spi) {     enum chips chip = spi_get_device_id(spi)->driver_data;     struct max1111_data *data;     int err;      spi->bits_per_word = 8;     spi->mode = spi_mode_0;     err = spi_setup(spi);     if (err < 0)         return err;      data = devm_kzalloc(&spi->dev, sizeof(struct max1111_data), gfp_kernel);     if (data == null) {         dev_err(&spi->dev, "failed allocate memory\n");         return -enomem;     }      switch (chip) {     case max1110:         data->lsb = 8;         data->sel_sh = max1110_ctrl_sel_sh;         break;     case max1111:         data->lsb = 8;         data->sel_sh = max1111_ctrl_sel_sh;         break;     case max1112:         data->lsb = 16;         data->sel_sh = max1110_ctrl_sel_sh;         break;     case max1113:         data->lsb = 16;         data->sel_sh = max1111_ctrl_sel_sh;         break;     }     err = setup_transfer(data);     if (err)         return err;      mutex_init(&data->drvdata_lock);      data->spi = spi;     spi_set_drvdata(spi, data);      err = sysfs_create_group(&spi->dev.kobj, &max1111_attr_group);     if (err) {         dev_err(&spi->dev, "failed create attribute group\n");         return err;     }     if (chip == max1110 || chip == max1112) {         err = sysfs_create_group(&spi->dev.kobj, &max1110_attr_group);         if (err) {             dev_err(&spi->dev,                 "failed create extended attribute group\n");             goto err_remove;         }     }      data->hwmon_dev = hwmon_device_register(&spi->dev);     if (is_err(data->hwmon_dev)) {         dev_err(&spi->dev, "failed create hwmon device\n");         err = ptr_err(data->hwmon_dev);         goto err_remove;     }  #ifdef config_sharpsl_pm     the_max1111 = data; #endif     return 0;  err_remove:     sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group);     sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);     return err; }  static int max1111_remove(struct spi_device *spi) {     struct max1111_data *data = spi_get_drvdata(spi);      hwmon_device_unregister(data->hwmon_dev);     sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group);     sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);     mutex_destroy(&data->drvdata_lock);     return 0; }  static const struct spi_device_id max1111_ids[] = {     { "max1110", max1110 },     { "max1111", max1111 },     { "max1112", max1112 },     { "max1113", max1113 },     { }, }; module_device_table(spi, max1111_ids);  static struct spi_driver max1111_driver = {     .driver     = {         .name   = "max1111",         .owner  = this_module,     },     .id_table   = max1111_ids,     .probe      = max1111_probe,     .remove     = max1111_remove, };  module_spi_driver(max1111_driver);  module_author("eric miao <eric.miao@marvell.com>"); module_description("max1110/max1111/max1112/max1113 adc driver"); module_license("gpl"); 

spi device driver (max1111 in case) pointer underlying spi-controller (struct spi_device *spi) during probe stage (max1111_probe). driver should use send requests controller (using spi_sync, example). driver doesn't know pins spi-controller use.

what spi-controller passed spi device driver? spi device, should declared in dts-file inside spi-controller node. controller initialized spi-controller node passed device probe.

spi-controller can hardware (specific soc), or spi-gpio. in case of hardware spi, pins dedicated , specified in soc trm. in case of spi-gpio, gpio names specified inside dts-properties of spi-gpio. properties names are: gpio-sck, gpio-miso, gpio-mosi, num-chipselects , cs-gpios (list).


Comments

Popular posts from this blog

python - No exponential form of the z-axis in matplotlib-3D-plots -

php - Best Light server (Linux + Web server + Database) for Raspberry Pi -

c# - "Newtonsoft.Json.JsonSerializationException unable to find constructor to use for types" error when deserializing class -