SPI設備註冊過程
開發板:tiny4412SDK + S702 + 4GB Flash
要移植的核心版本:Linux-4.4.0 (支援device tree)
u-boot版本:友善之臂自帶的 U-Boot 2010.12
busybox版本:busybox 1.25
目標:
同 i2c 一樣,分析 spi 裝置的註冊過程,其實是一模一樣的。
int spi_register_master(struct spi_master *master) //註冊控制器驅動
of_register_spi_devices(master);
for_each_available_child_of_node(master->dev.of_node, nc) //控制器節點的子節點
of_register_spi_device(master, nc);
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
static struct spi_device * of_register_spi_device(struct spi_master *master, struct device_node *nc)
{
struct spi_device *spi;
int rc;
u32 value;
/* 分配一個 spi device ,從屬於 master*/
spi = spi_alloc_device(master);
/* 獲取 compatibel 屬性,具體看後邊 */
rc = of_modalias_node(nc, spi->modalias, sizeof(spi->modalias));
/* 獲取 reg 屬性作為片選編號 */
rc = of_property_read_u32(nc, "reg", &value);
spi->chip_select = value;
/* mode 設定 */
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;
if (of_find_property(nc, "spi-3wire", NULL))
spi->mode |= SPI_3WIRE;
if (of_find_property(nc, "spi-lsb-first", NULL))
spi->mode |= SPI_LSB_FIRST;
/* Device DUAL/QUAD mode */
if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
switch (value) {
case 1:
break;
case 2:
spi->mode |= SPI_TX_DUAL;
break;
case 4:
spi->mode |= SPI_TX_QUAD;
break;
default:
dev_warn(&master->dev,
"spi-tx-bus-width %d not supported\n",
value);
break;
}
}
if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) {
switch (value) {
case 1:
break;
case 2:
spi->mode |= SPI_RX_DUAL;
break;
case 4:
spi->mode |= SPI_RX_QUAD;
break;
default:
dev_warn(&master->dev,
"spi-rx-bus-width %d not supported\n",
value);
break;
}
}
/* 獲取最大速度 */
rc = of_property_read_u32(nc, "spi-max-frequency", &value);
spi->max_speed_hz = value;
/* Store a pointer to the node in the device structure */
of_node_get(nc);
spi->dev.of_node = nc;
/* 註冊 spi device */
rc = spi_add_device(spi);
return spi;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
int of_modalias_node(struct device_node *node, char *modalias, int len)
{
const char *compatible, *p;
int cplen;
compatible = of_get_property(node, "compatible", &cplen);
if (!compatible || strlen(compatible) > cplen)
return -ENODEV;
p = strchr(compatible, ',');
strlcpy(modalias, p ? p + 1 : compatible, len);//如果compatibel屬性中有“,”則取“,”之後的內容,否則取全部,它作為匹配依據
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
static int spi_match_device(struct device *dev, struct device_driver *drv)
{
const struct spi_device *spi = to_spi_device(dev);
const struct spi_driver *sdrv = to_spi_driver(drv);
if (sdrv->id_table)
return !!spi_match_id(sdrv->id_table, spi);
return strcmp(spi->modalias, drv->name) == 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
static const struct spi_device_id *spi_match_id(const struct spi_device_id *id, const struct spi_device *sdev)
{
while (id->name[0]) {
if (!strcmp(sdev->modalias, id->name))
return id;
id++;
}
return NULL;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
啟動報錯:
[ 0.962673] spi spi0.0: child node 'controller-data' not found
[ 0.968455] spi spi0.0: No CS for SPI(0)
[ 0.972360] s3c64xx-spi 13920000.spi: can't setup spi0.0, status -19
[ 0.978693] spi_device register error /[email protected]13920000/[email protected]0
[ 0.984339] spi_master spi0: Failed to create SPI device for /[email protected]13920000/s0
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
struct spi_master *master = spi->master;
struct device *dev = master->dev.parent;
int status;
/* Chipselects are numbered 0..max; validate. */
if (spi->chip_select >= master->num_chipselect)
/* Set the bus ID string */
spi_dev_set_name(spi);
mutex_lock(&spi_add_lock);
status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
if (master->cs_gpios)
spi->cs_gpio = master->cs_gpios[spi->chip_select];
status = spi_setup(spi);
if (status < 0) {
dev_err(dev, "can't setup %s, status %d\n", dev_name(&spi->dev), status);
goto done;
}
/* Device may be bound to an active driver when this returns */
status = device_add(&spi->dev);
if (status < 0)
dev_err(dev, "can't add %s, status %d\n",
dev_name(&spi->dev), status);
else
dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
done:
mutex_unlock(&spi_add_lock);
return status;
}
EXPORT_SYMBOL_GPL(spi_add_device);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
static int s3c64xx_spi_setup(struct spi_device *spi)
{
struct s3c64xx_spi_csinfo *cs = spi->controller_data;
struct s3c64xx_spi_driver_data *sdd;
struct s3c64xx_spi_info *sci;
int err;
sdd = spi_master_get_devdata(spi->master);
if (spi->dev.of_node) {
cs = s3c64xx_get_slave_ctrldata(spi);
spi->controller_data = cs;
} else if (cs) {
/* On non-DT platforms the SPI core will set spi->cs_gpio
* to -ENOENT. The GPIO pin used to drive the chip select
* is defined by using platform data so spi->cs_gpio value
* has to be override to have the proper GPIO pin number.
*/
spi->cs_gpio = cs->line;
}
if (IS_ERR_OR_NULL(cs)) {
dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
return -ENODEV;
}
if (!spi_get_ctldata(spi)) {
if (gpio_is_valid(spi->cs_gpio)) {
err = gpio_request_one(spi->cs_gpio, GPIOF_OUT_INIT_HIGH,
dev_name(&spi->dev));
if (err) {
dev_err(&spi->dev,
"Failed to get /CS gpio [%d]: %d\n",
spi->cs_gpio, err);
goto err_gpio_req;
}
}
spi_set_ctldata(spi, cs);
}
sci = sdd->cntrlr_info;
pm_runtime_get_sync(&sdd->pdev->dev);
/* Check if we can provide the requested rate */
if (!sdd->port_conf->clk_from_cmu) {
u32 psr, speed;
/* Max possible */
speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
if (spi->max_speed_hz > speed)
spi->max_speed_hz = speed;
psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
psr &= S3C64XX_SPI_PSR_MASK;
if (psr == S3C64XX_SPI_PSR_MASK)
psr--;
speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
if (spi->max_speed_hz < speed) {
if (psr+1 < S3C64XX_SPI_PSR_MASK) {
psr++;
} else {
err = -EINVAL;
goto setup_exit;
}
}
speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
if (spi->max_speed_hz >= speed) {
spi->max_speed_hz = speed;
} else {
dev_err(&spi->dev, "Can't set %dHz transfer speed\n",
spi->max_speed_hz);
err = -EINVAL;
goto setup_exit;
}
}
pm_runtime_mark_last_busy(&sdd->pdev->dev);
pm_runtime_put_autosuspend(&sdd->pdev->dev);
if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
return 0;
setup_exit:
pm_runtime_mark_last_busy(&sdd->pdev->dev);
pm_runtime_put_autosuspend(&sdd->pdev->dev);
/* setup() returns with device de-selected */
if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
if (gpio_is_valid(spi->cs_gpio))
gpio_free(spi->cs_gpio);
spi_set_ctldata(spi, NULL);
err_gpio_req:
if (spi->dev.of_node)
kfree(cs);
return err;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( struct spi_device *spi)
{
struct s3c64xx_spi_csinfo *cs;
struct device_node *slave_np, *data_np = NULL;
u32 fb_delay = 0;
slave_np = spi->dev.of_node;
if (!slave_np) {
dev_err(&spi->dev, "device node not found\n");
return ERR_PTR(-EINVAL);
}
data_np = of_get_child_by_name(slave_np, "controller-data");
if (!data_np) {
dev_err(&spi->dev, "child node 'controller-data' not found\n");
return ERR_PTR(-EINVAL);
}
cs = kzalloc(sizeof(*cs), GFP_KERNEL);
if (!cs) {
of_node_put(data_np);
return ERR_PTR(-ENOMEM);
}
of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
cs->fb_delay = fb_delay;
of_node_put(data_np);
return cs;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
最開始,就是因為沒有指定 controller-data 導致裝置無法匹配到驅動程式,查了半天。下面給出後面要寫的 spi flash 的裝置樹:
&spi_0 {
status = "okay";
cs-gpios = <&gpb 1 GPIO_ACTIVE_HIGH>;
[email protected]0 {
compatible = "tiny4412,spi_flash";
spi-max-frequency = <10000000>;
reg = <0>;
controller-data {
samsung,spi-feedback-delay = <0>;
};
};
};
相關推薦
裝置樹學習之(九)SPI設備註冊過程
開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busy
SPI設備註冊過程
開發板:tiny4412SDK + S702 + 4GB Flash 要移植的核心版本:Linux-4.4.0 (支援device tree) u-boot版本:友善之臂自帶的 U-Boot 2010.12 busybox版本:busybox 1.25 目標: 同 i
I2C匯流排設備註冊過程
轉自 http://lhsblog01.blog.163.com/blog/static/1020045192010221103944423/i2c bus i2c匯流排使用 platform_device實現, 匯流排驅動用platform_driver實現. 在註冊i2c_bus時,會把與這個BUS相
QCom MSM平臺顯示屏Framebuffer設備註冊過程
本文是Android Display部分分析的一部分,描述屏Framebuffer設備註冊過程。 QC MSM7xxx/MSM8xxx平臺本身就提供了很多介面的屏的支援,每種屏對應一個驅動檔案。由於QC MSM平臺顯示驅動架構做了絕大部分的工作,驅動一塊新的屏僅需要做很少量的工作。下面的過程是屏Frameb
v4l2 video設備註冊和呼叫過程
一、 註冊一個video_device裝置 它代表系統/dev/videox裝置節點的實際的物理裝置。 下邊一核心版本2.6.32種成熟的omap2432處理器攝像頭控制器模組驅動為例分析: 下邊的程式碼在driver/media/video/omap24xxcam.c中
十二 v4l2 video設備註冊和呼叫過程
一、 註冊一個video_device裝置 它代表系統/dev/videox裝置節點的實際的物理裝置。 下邊一核心版本2.6.32種成熟的omap2432處理器攝像頭控制器模組驅動為例分析: 下邊的程式碼在driver/media/video/omap24xxcam.c中 1、Video device的操
Linux:驅動之字元設備註冊新介面(未完)
驅動之字元設備註冊新介面 目前尚不是最終版本,還望有心人自己學習的時候,把自己整合的知識點相關的答案也好問題也好,或者實踐過程中的一些操作截圖,再或者其他的一些想要分享材料發給筆者郵箱:[email protected],我們一起完善這篇部落格!筆者寫這篇部
設備註冊、驅動註冊以及雜項設備註冊之間的關係
1.裝置宣告是在平臺檔案/home/leizi/android/iTop4412_Kernel_3.0/arch/arm/mach-exynos/mach-itop4412.c中,如下圖,並且裝置名稱是led_two. 核心編譯之後,s3c_device_leds_ctl
platform_device_系列函式及其設備註冊的作用
platform_device_系列函式,實際上是註冊了一個叫platform的虛擬匯流排。使用約定是如果一個不屬於任何匯流排的裝置,例如藍芽,串列埠等裝置,都需要掛在這個虛擬總線上。 river/base/platform.c //platform裝置宣告 struct
Linux kernel 有關 spi 設備樹參數解析
-c enable pre ann driver error ola state AC 最近做了一個 spi 設備驅動從板級設備驅動升級到設備樹設備驅動,這其中要了解 spi 設備樹代碼的解析。 設備樹配置如下: 503 &spi0 { 504 statu
ISE主備註冊和同步
Synchronize Primary and Secondary Cisco ISE Nodes You can make configuration changes to Cisco ISE only through the Primary PAN. The configuration changes g
Spring ConfigurationClassPostProcessor Bean解析及自注冊過程
一、Bean的自注冊過程 二、自注冊過程說明 ConfigurationClassParser解析流程 1、處理@PropertySources註解,配置資訊的解析 2、處理@ComponentScan註解:使用ComponentScanAnnotationParser掃描baseP
linux驅動編寫32位與64位設備註意事項
Linux 64 位體系結構 不幸的是,C 程式語言並沒有提供一種機制來新增新的基本資料型別。因此,提供 64 位的定址和整數運算能力必須要修改現有資料型別的繫結或對映,或者向 C 語言中新增新的資料型別。 表 1. 32 位和 64 位資料模型 ILP32 LP64 LLP64
Mysql儲存過程4:mysql變量設置
from 默認 pan procedure weight use mysql變量 sql 寫法 默認全局變量是兩個@@開頭, 可用show variables查看所有默認變量: @@user #declare定義變量只能用在儲存過程中 #declare 變量名 數據類型
Nhibernate/Hibernate 使用存儲過程 多參數設置
ner map ini names project als service location work <?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:n
(轉)關於Tomcat的點點滴滴(體系架構、處理http請求的過程、安裝和配置、目錄結構、設置壓縮和對中文文件名的支持、以及Catalina這個名字的由來……等)
https 設置 重啟 specific 調用 持久化數據 所在 original apps 轉自:http://itfish.net/article/41668.html 總結Tomcat的體系架構、處理http請求的過程、安裝和配置、目錄結構、設置壓縮和對中文文件名
H5調用設備攝像頭和系統相冊
camera 系統相冊 capture 調用 設備 accept 攝像 acc ima 1.調用設備攝像頭 <input type="file" accept="image/*" capture="camera"> 2.調用系統相冊 <inp
STM32F407 讀保護,寫保護,解鎖過程【芯片已設置讀保護,無法讀取更多信息】
寫保護 stm32f407 讀保護 解鎖過程 硬件準備:CH340 USB轉TTL串口一個STM32F407 板子一塊設置從ISP啟動軟件準備:1,flash_loader_demo_v2.8.0.exe 或者 FlashLoader Demonstrator 2.8.0.msi 都可以下載地址:
設置Sql server用戶對表、視圖、存儲過程、架構的增刪改查權限
例如 ont 函數 權限控制 str 角色 -s 簡單 管理 根據數據庫Schema限制用戶對數據庫的操作行為 授予Shema dbo下對象的定義權限給某個用戶(也就是說該用戶可以修改架構dbo下所有表/視圖/存儲過程/函數的結構) use [Your DB N
MPS添加管理設備實例NS的過程
-a enable pan pass password ren eat gateway tor MPS添加管理設備實例NS的過程 MPS添加實例NS設備節點: Jan 25 18:25:05 <local0.info> mpsvpx mas_se