Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
d65d830c
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d65d830c
编写于
7月 28, 2008
作者:
B
Benjamin Herrenschmidt
浏览文件
操作
浏览文件
下载
差异文件
Merge commit 'gcl/gcl-next'
上级
837b41b5
284b0189
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
317 addition
and
105 deletion
+317
-105
drivers/of/Kconfig
drivers/of/Kconfig
+6
-0
drivers/of/Makefile
drivers/of/Makefile
+1
-0
drivers/of/base.c
drivers/of/base.c
+88
-0
drivers/of/of_i2c.c
drivers/of/of_i2c.c
+3
-61
drivers/of/of_spi.c
drivers/of/of_spi.c
+93
-0
drivers/spi/spi.c
drivers/spi/spi.c
+95
-44
include/linux/of.h
include/linux/of.h
+1
-0
include/linux/of_spi.h
include/linux/of_spi.h
+18
-0
include/linux/spi/spi.h
include/linux/spi/spi.h
+12
-0
未找到文件。
drivers/of/Kconfig
浏览文件 @
d65d830c
...
...
@@ -13,3 +13,9 @@ config OF_I2C
depends on PPC_OF && I2C
help
OpenFirmware I2C accessors
config OF_SPI
def_tristate SPI
depends on OF && PPC_OF && SPI
help
OpenFirmware SPI accessors
drivers/of/Makefile
浏览文件 @
d65d830c
...
...
@@ -2,3 +2,4 @@ obj-y = base.o
obj-$(CONFIG_OF_DEVICE)
+=
device.o platform.o
obj-$(CONFIG_OF_GPIO)
+=
gpio.o
obj-$(CONFIG_OF_I2C)
+=
of_i2c.o
obj-$(CONFIG_OF_SPI)
+=
of_spi.o
drivers/of/base.c
浏览文件 @
d65d830c
...
...
@@ -385,3 +385,91 @@ struct device_node *of_find_matching_node(struct device_node *from,
return
np
;
}
EXPORT_SYMBOL
(
of_find_matching_node
);
/**
* of_modalias_table: Table of explicit compatible ==> modalias mappings
*
* This table allows particulare compatible property values to be mapped
* to modalias strings. This is useful for busses which do not directly
* understand the OF device tree but are populated based on data contained
* within the device tree. SPI and I2C are the two current users of this
* table.
*
* In most cases, devices do not need to be listed in this table because
* the modalias value can be derived directly from the compatible table.
* However, if for any reason a value cannot be derived, then this table
* provides a method to override the implicit derivation.
*
* At the moment, a single table is used for all bus types because it is
* assumed that the data size is small and that the compatible values
* should already be distinct enough to differentiate between SPI, I2C
* and other devices.
*/
struct
of_modalias_table
{
char
*
of_device
;
char
*
modalias
;
};
static
struct
of_modalias_table
of_modalias_table
[]
=
{
/* Empty for now; add entries as needed */
};
/**
* of_modalias_node - Lookup appropriate modalias for a device node
* @node: pointer to a device tree node
* @modalias: Pointer to buffer that modalias value will be copied into
* @len: Length of modalias value
*
* Based on the value of the compatible property, this routine will determine
* an appropriate modalias value for a particular device tree node. Three
* separate methods are used to derive a modalias value.
*
* First method is to lookup the compatible value in of_modalias_table.
* Second is to look for a "linux,<modalias>" entry in the compatible list
* and used that for modalias. Third is to strip off the manufacturer
* prefix from the first compatible entry and use the remainder as modalias
*
* This routine returns 0 on success
*/
int
of_modalias_node
(
struct
device_node
*
node
,
char
*
modalias
,
int
len
)
{
int
i
,
cplen
;
const
char
*
compatible
;
const
char
*
p
;
/* 1. search for exception list entry */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
of_modalias_table
);
i
++
)
{
compatible
=
of_modalias_table
[
i
].
of_device
;
if
(
!
of_device_is_compatible
(
node
,
compatible
))
continue
;
strlcpy
(
modalias
,
of_modalias_table
[
i
].
modalias
,
len
);
return
0
;
}
compatible
=
of_get_property
(
node
,
"compatible"
,
&
cplen
);
if
(
!
compatible
)
return
-
ENODEV
;
/* 2. search for linux,<modalias> entry */
p
=
compatible
;
while
(
cplen
>
0
)
{
if
(
!
strncmp
(
p
,
"linux,"
,
6
))
{
p
+=
6
;
strlcpy
(
modalias
,
p
,
len
);
return
0
;
}
i
=
strlen
(
p
)
+
1
;
p
+=
i
;
cplen
-=
i
;
}
/* 3. take first compatible entry and strip manufacturer */
p
=
strchr
(
compatible
,
','
);
if
(
!
p
)
return
-
ENODEV
;
p
++
;
strlcpy
(
modalias
,
p
,
len
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
of_modalias_node
);
drivers/of/of_i2c.c
浏览文件 @
d65d830c
...
...
@@ -16,62 +16,6 @@
#include <linux/of_i2c.h>
#include <linux/module.h>
struct
i2c_driver_device
{
char
*
of_device
;
char
*
i2c_type
;
};
static
struct
i2c_driver_device
i2c_devices
[]
=
{
};
static
int
of_find_i2c_driver
(
struct
device_node
*
node
,
struct
i2c_board_info
*
info
)
{
int
i
,
cplen
;
const
char
*
compatible
;
const
char
*
p
;
/* 1. search for exception list entry */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
i2c_devices
);
i
++
)
{
if
(
!
of_device_is_compatible
(
node
,
i2c_devices
[
i
].
of_device
))
continue
;
if
(
strlcpy
(
info
->
type
,
i2c_devices
[
i
].
i2c_type
,
I2C_NAME_SIZE
)
>=
I2C_NAME_SIZE
)
return
-
ENOMEM
;
return
0
;
}
compatible
=
of_get_property
(
node
,
"compatible"
,
&
cplen
);
if
(
!
compatible
)
return
-
ENODEV
;
/* 2. search for linux,<i2c-type> entry */
p
=
compatible
;
while
(
cplen
>
0
)
{
if
(
!
strncmp
(
p
,
"linux,"
,
6
))
{
p
+=
6
;
if
(
strlcpy
(
info
->
type
,
p
,
I2C_NAME_SIZE
)
>=
I2C_NAME_SIZE
)
return
-
ENOMEM
;
return
0
;
}
i
=
strlen
(
p
)
+
1
;
p
+=
i
;
cplen
-=
i
;
}
/* 3. take fist compatible entry and strip manufacturer */
p
=
strchr
(
compatible
,
','
);
if
(
!
p
)
return
-
ENODEV
;
p
++
;
if
(
strlcpy
(
info
->
type
,
p
,
I2C_NAME_SIZE
)
>=
I2C_NAME_SIZE
)
return
-
ENOMEM
;
return
0
;
}
void
of_register_i2c_devices
(
struct
i2c_adapter
*
adap
,
struct
device_node
*
adap_node
)
{
...
...
@@ -83,6 +27,9 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
const
u32
*
addr
;
int
len
;
if
(
of_modalias_node
(
node
,
info
.
type
,
sizeof
(
info
.
type
))
<
0
)
continue
;
addr
=
of_get_property
(
node
,
"reg"
,
&
len
);
if
(
!
addr
||
len
<
sizeof
(
int
)
||
*
addr
>
(
1
<<
10
)
-
1
)
{
printk
(
KERN_ERR
...
...
@@ -92,11 +39,6 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
info
.
irq
=
irq_of_parse_and_map
(
node
,
0
);
if
(
of_find_i2c_driver
(
node
,
&
info
)
<
0
)
{
irq_dispose_mapping
(
info
.
irq
);
continue
;
}
info
.
addr
=
*
addr
;
request_module
(
info
.
type
);
...
...
drivers/of/of_spi.c
0 → 100644
浏览文件 @
d65d830c
/*
* 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
;
/* 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
);
drivers/spi/spi.c
浏览文件 @
d65d830c
...
...
@@ -178,6 +178,96 @@ struct boardinfo {
static
LIST_HEAD
(
board_list
);
static
DEFINE_MUTEX
(
board_lock
);
/**
* spi_alloc_device - Allocate a new SPI device
* @master: Controller to which device is connected
* Context: can sleep
*
* Allows a driver to allocate and initialize a spi_device without
* registering it immediately. This allows a driver to directly
* fill the spi_device with device parameters before calling
* spi_add_device() on it.
*
* Caller is responsible to call spi_add_device() on the returned
* spi_device structure to add it to the SPI master. If the caller
* needs to discard the spi_device without adding it, then it should
* call spi_dev_put() on it.
*
* Returns a pointer to the new device, or NULL.
*/
struct
spi_device
*
spi_alloc_device
(
struct
spi_master
*
master
)
{
struct
spi_device
*
spi
;
struct
device
*
dev
=
master
->
dev
.
parent
;
if
(
!
spi_master_get
(
master
))
return
NULL
;
spi
=
kzalloc
(
sizeof
*
spi
,
GFP_KERNEL
);
if
(
!
spi
)
{
dev_err
(
dev
,
"cannot alloc spi_device
\n
"
);
spi_master_put
(
master
);
return
NULL
;
}
spi
->
master
=
master
;
spi
->
dev
.
parent
=
dev
;
spi
->
dev
.
bus
=
&
spi_bus_type
;
spi
->
dev
.
release
=
spidev_release
;
device_initialize
(
&
spi
->
dev
);
return
spi
;
}
EXPORT_SYMBOL_GPL
(
spi_alloc_device
);
/**
* spi_add_device - Add spi_device allocated with spi_alloc_device
* @spi: spi_device to register
*
* Companion function to spi_alloc_device. Devices allocated with
* spi_alloc_device can be added onto the spi bus with this function.
*
* Returns 0 on success; non-zero on failure
*/
int
spi_add_device
(
struct
spi_device
*
spi
)
{
struct
device
*
dev
=
spi
->
master
->
dev
.
parent
;
int
status
;
/* Chipselects are numbered 0..max; validate. */
if
(
spi
->
chip_select
>=
spi
->
master
->
num_chipselect
)
{
dev_err
(
dev
,
"cs%d >= max %d
\n
"
,
spi
->
chip_select
,
spi
->
master
->
num_chipselect
);
return
-
EINVAL
;
}
/* Set the bus ID string */
snprintf
(
spi
->
dev
.
bus_id
,
sizeof
spi
->
dev
.
bus_id
,
"%s.%u"
,
spi
->
master
->
dev
.
bus_id
,
spi
->
chip_select
);
/* drivers may modify this initial i/o setup */
status
=
spi
->
master
->
setup
(
spi
);
if
(
status
<
0
)
{
dev_err
(
dev
,
"can't %s %s, status %d
\n
"
,
"setup"
,
spi
->
dev
.
bus_id
,
status
);
return
status
;
}
/* driver core catches callers that misbehave by defining
* devices that already exist.
*/
status
=
device_add
(
&
spi
->
dev
);
if
(
status
<
0
)
{
dev_err
(
dev
,
"can't %s %s, status %d
\n
"
,
"add"
,
spi
->
dev
.
bus_id
,
status
);
return
status
;
}
dev_dbg
(
dev
,
"registered child %s
\n
"
,
spi
->
dev
.
bus_id
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
spi_add_device
);
/**
* spi_new_device - instantiate one new SPI device
...
...
@@ -197,7 +287,6 @@ struct spi_device *spi_new_device(struct spi_master *master,
struct
spi_board_info
*
chip
)
{
struct
spi_device
*
proxy
;
struct
device
*
dev
=
master
->
dev
.
parent
;
int
status
;
/* NOTE: caller did any chip->bus_num checks necessary.
...
...
@@ -207,66 +296,28 @@ struct spi_device *spi_new_device(struct spi_master *master,
* suggests syslogged diagnostics are best here (ugh).
*/
/* Chipselects are numbered 0..max; validate. */
if
(
chip
->
chip_select
>=
master
->
num_chipselect
)
{
dev_err
(
dev
,
"cs%d > max %d
\n
"
,
chip
->
chip_select
,
master
->
num_chipselect
);
return
NULL
;
}
if
(
!
spi_master_get
(
master
))
proxy
=
spi_alloc_device
(
master
);
if
(
!
proxy
)
return
NULL
;
WARN_ON
(
strlen
(
chip
->
modalias
)
>=
sizeof
(
proxy
->
modalias
));
proxy
=
kzalloc
(
sizeof
*
proxy
,
GFP_KERNEL
);
if
(
!
proxy
)
{
dev_err
(
dev
,
"can't alloc dev for cs%d
\n
"
,
chip
->
chip_select
);
goto
fail
;
}
proxy
->
master
=
master
;
proxy
->
chip_select
=
chip
->
chip_select
;
proxy
->
max_speed_hz
=
chip
->
max_speed_hz
;
proxy
->
mode
=
chip
->
mode
;
proxy
->
irq
=
chip
->
irq
;
strlcpy
(
proxy
->
modalias
,
chip
->
modalias
,
sizeof
(
proxy
->
modalias
));
snprintf
(
proxy
->
dev
.
bus_id
,
sizeof
proxy
->
dev
.
bus_id
,
"%s.%u"
,
master
->
dev
.
bus_id
,
chip
->
chip_select
);
proxy
->
dev
.
parent
=
dev
;
proxy
->
dev
.
bus
=
&
spi_bus_type
;
proxy
->
dev
.
platform_data
=
(
void
*
)
chip
->
platform_data
;
proxy
->
controller_data
=
chip
->
controller_data
;
proxy
->
controller_state
=
NULL
;
proxy
->
dev
.
release
=
spidev_release
;
/* drivers may modify this initial i/o setup */
status
=
master
->
setup
(
proxy
);
status
=
spi_add_device
(
proxy
);
if
(
status
<
0
)
{
dev_err
(
dev
,
"can't %s %s, status %d
\n
"
,
"setup"
,
proxy
->
dev
.
bus_id
,
status
);
goto
fail
;
spi_dev_put
(
proxy
);
return
NULL
;
}
/* driver core catches callers that misbehave by defining
* devices that already exist.
*/
status
=
device_register
(
&
proxy
->
dev
);
if
(
status
<
0
)
{
dev_err
(
dev
,
"can't %s %s, status %d
\n
"
,
"add"
,
proxy
->
dev
.
bus_id
,
status
);
goto
fail
;
}
dev_dbg
(
dev
,
"registered child %s
\n
"
,
proxy
->
dev
.
bus_id
);
return
proxy
;
fail:
spi_master_put
(
master
);
kfree
(
proxy
);
return
NULL
;
}
EXPORT_SYMBOL_GPL
(
spi_new_device
);
...
...
include/linux/of.h
浏览文件 @
d65d830c
...
...
@@ -70,5 +70,6 @@ extern int of_n_addr_cells(struct device_node *np);
extern
int
of_n_size_cells
(
struct
device_node
*
np
);
extern
const
struct
of_device_id
*
of_match_node
(
const
struct
of_device_id
*
matches
,
const
struct
device_node
*
node
);
extern
int
of_modalias_node
(
struct
device_node
*
node
,
char
*
modalias
,
int
len
);
#endif
/* _LINUX_OF_H */
include/linux/of_spi.h
0 → 100644
浏览文件 @
d65d830c
/*
* OpenFirmware SPI support routines
* Copyright (C) 2008 Secret Lab Technologies Ltd.
*
* Support routines for deriving SPI device attachments from the device
* tree.
*/
#ifndef __LINUX_OF_SPI_H
#define __LINUX_OF_SPI_H
#include <linux/of.h>
#include <linux/spi/spi.h>
extern
void
of_register_spi_devices
(
struct
spi_master
*
master
,
struct
device_node
*
np
);
#endif
/* __LINUX_OF_SPI */
include/linux/spi/spi.h
浏览文件 @
d65d830c
...
...
@@ -778,7 +778,19 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
* use spi_new_device() to describe each device. You can also call
* spi_unregister_device() to start making that device vanish, but
* normally that would be handled by spi_unregister_master().
*
* You can also use spi_alloc_device() and spi_add_device() to use a two
* stage registration sequence for each spi_device. This gives the caller
* some more control over the spi_device structure before it is registered,
* but requires that caller to initialize fields that would otherwise
* be defined using the board info.
*/
extern
struct
spi_device
*
spi_alloc_device
(
struct
spi_master
*
master
);
extern
int
spi_add_device
(
struct
spi_device
*
spi
);
extern
struct
spi_device
*
spi_new_device
(
struct
spi_master
*
,
struct
spi_board_info
*
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录