Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
a18d7f96
Commit
a18d7f96
authored
Jul 10, 2012
by
Paul Mundt
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'common/pfc' into common/pinctrl
parents
2437fccf
afae021a
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
953 additions
and
18 deletions
+953
-18
drivers/sh/Kconfig
drivers/sh/Kconfig
+1
-0
drivers/sh/Makefile
drivers/sh/Makefile
+2
-1
drivers/sh/pfc/Kconfig
drivers/sh/pfc/Kconfig
+14
-0
drivers/sh/pfc/Makefile
drivers/sh/pfc/Makefile
+2
-0
drivers/sh/pfc/core.c
drivers/sh/pfc/core.c
+578
-0
drivers/sh/pfc/gpio.c
drivers/sh/pfc/gpio.c
+309
-0
include/linux/sh_pfc.h
include/linux/sh_pfc.h
+47
-17
No files found.
drivers/sh/Kconfig
View file @
a18d7f96
menu "SuperH / SH-Mobile Driver Options"
menu "SuperH / SH-Mobile Driver Options"
source "drivers/sh/intc/Kconfig"
source "drivers/sh/intc/Kconfig"
source "drivers/sh/pfc/Kconfig"
endmenu
endmenu
drivers/sh/Makefile
View file @
a18d7f96
...
@@ -5,6 +5,7 @@ obj-y := intc/
...
@@ -5,6 +5,7 @@ obj-y := intc/
obj-$(CONFIG_HAVE_CLK)
+=
clk/
obj-$(CONFIG_HAVE_CLK)
+=
clk/
obj-$(CONFIG_MAPLE)
+=
maple/
obj-$(CONFIG_MAPLE)
+=
maple/
obj-$(CONFIG_SH_PFC)
+=
pfc/
obj-$(CONFIG_SUPERHYWAY)
+=
superhyway/
obj-$(CONFIG_SUPERHYWAY)
+=
superhyway/
obj-$(CONFIG_GENERIC_GPIO)
+=
pfc.o
obj-y
+=
pm_runtime.o
obj-y
+=
pm_runtime.o
drivers/sh/pfc/Kconfig
0 → 100644
View file @
a18d7f96
comment "Pin function controller options"
config SH_PFC
# XXX move off the gpio dependency
depends on GENERIC_GPIO
select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB
def_bool y
config GPIO_SH_PFC
tristate "SuperH PFC GPIO support"
depends on SH_PFC && GPIOLIB
help
This enables support for GPIOs within the SoC's pin function
controller.
drivers/sh/pfc/Makefile
0 → 100644
View file @
a18d7f96
obj-y
+=
core.o
obj-$(CONFIG_GPIO_SH_PFC)
+=
gpio.o
drivers/sh/pfc.c
→
drivers/sh/pfc
/core
.c
View file @
a18d7f96
/*
/*
*
Pinmuxed GPIO support for SuperH
.
*
SuperH Pin Function Controller support
.
*
*
* Copyright (C) 2008 Magnus Damm
* Copyright (C) 2008 Magnus Damm
* Copyright (C) 2009 - 2012 Paul Mundt
*
*
* This file is subject to the terms and conditions of the GNU General Public
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* License. See the file "COPYING" in the main directory of this archive
...
@@ -11,70 +12,74 @@
...
@@ -11,70 +12,74 @@
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/
list
.h>
#include <linux/
sh_pfc
.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/ioport.h>
static
void
pfc_iounmap
(
struct
pinmux_info
*
pip
)
static
struct
sh_pfc
*
sh_pfc
__read_mostly
;
static
inline
bool
sh_pfc_initialized
(
void
)
{
return
!!
sh_pfc
;
}
static
void
pfc_iounmap
(
struct
sh_pfc
*
pfc
)
{
{
int
k
;
int
k
;
for
(
k
=
0
;
k
<
p
ip
->
num_resources
;
k
++
)
for
(
k
=
0
;
k
<
p
fc
->
num_resources
;
k
++
)
if
(
p
ip
->
window
[
k
].
virt
)
if
(
p
fc
->
window
[
k
].
virt
)
iounmap
(
p
ip
->
window
[
k
].
virt
);
iounmap
(
p
fc
->
window
[
k
].
virt
);
kfree
(
p
ip
->
window
);
kfree
(
p
fc
->
window
);
p
ip
->
window
=
NULL
;
p
fc
->
window
=
NULL
;
}
}
static
int
pfc_ioremap
(
struct
pinmux_info
*
pip
)
static
int
pfc_ioremap
(
struct
sh_pfc
*
pfc
)
{
{
struct
resource
*
res
;
struct
resource
*
res
;
int
k
;
int
k
;
if
(
!
p
ip
->
num_resources
)
if
(
!
p
fc
->
num_resources
)
return
0
;
return
0
;
p
ip
->
window
=
kzalloc
(
pip
->
num_resources
*
sizeof
(
*
pip
->
window
),
p
fc
->
window
=
kzalloc
(
pfc
->
num_resources
*
sizeof
(
*
pfc
->
window
),
GFP_NOWAIT
);
GFP_NOWAIT
);
if
(
!
p
ip
->
window
)
if
(
!
p
fc
->
window
)
goto
err1
;
goto
err1
;
for
(
k
=
0
;
k
<
p
ip
->
num_resources
;
k
++
)
{
for
(
k
=
0
;
k
<
p
fc
->
num_resources
;
k
++
)
{
res
=
p
ip
->
resource
+
k
;
res
=
p
fc
->
resource
+
k
;
WARN_ON
(
resource_type
(
res
)
!=
IORESOURCE_MEM
);
WARN_ON
(
resource_type
(
res
)
!=
IORESOURCE_MEM
);
p
ip
->
window
[
k
].
phys
=
res
->
start
;
p
fc
->
window
[
k
].
phys
=
res
->
start
;
p
ip
->
window
[
k
].
size
=
resource_size
(
res
);
p
fc
->
window
[
k
].
size
=
resource_size
(
res
);
p
ip
->
window
[
k
].
virt
=
ioremap_nocache
(
res
->
start
,
p
fc
->
window
[
k
].
virt
=
ioremap_nocache
(
res
->
start
,
resource_size
(
res
));
resource_size
(
res
));
if
(
!
p
ip
->
window
[
k
].
virt
)
if
(
!
p
fc
->
window
[
k
].
virt
)
goto
err2
;
goto
err2
;
}
}
return
0
;
return
0
;
err2:
err2:
pfc_iounmap
(
p
ip
);
pfc_iounmap
(
p
fc
);
err1:
err1:
return
-
1
;
return
-
1
;
}
}
static
void
__iomem
*
pfc_phys_to_virt
(
struct
pinmux_info
*
pip
,
static
void
__iomem
*
pfc_phys_to_virt
(
struct
sh_pfc
*
pfc
,
unsigned
long
address
)
unsigned
long
address
)
{
{
struct
pfc_window
*
window
;
struct
pfc_window
*
window
;
int
k
;
int
k
;
/* scan through physical windows and convert address */
/* scan through physical windows and convert address */
for
(
k
=
0
;
k
<
p
ip
->
num_resources
;
k
++
)
{
for
(
k
=
0
;
k
<
p
fc
->
num_resources
;
k
++
)
{
window
=
p
ip
->
window
+
k
;
window
=
p
fc
->
window
+
k
;
if
(
address
<
window
->
phys
)
if
(
address
<
window
->
phys
)
continue
;
continue
;
...
@@ -135,8 +140,7 @@ static void gpio_write_raw_reg(void __iomem *mapped_reg,
...
@@ -135,8 +140,7 @@ static void gpio_write_raw_reg(void __iomem *mapped_reg,
BUG
();
BUG
();
}
}
static
int
gpio_read_bit
(
struct
pinmux_data_reg
*
dr
,
int
sh_pfc_read_bit
(
struct
pinmux_data_reg
*
dr
,
unsigned
long
in_pos
)
unsigned
long
in_pos
)
{
{
unsigned
long
pos
;
unsigned
long
pos
;
...
@@ -147,9 +151,10 @@ static int gpio_read_bit(struct pinmux_data_reg *dr,
...
@@ -147,9 +151,10 @@ static int gpio_read_bit(struct pinmux_data_reg *dr,
return
(
gpio_read_raw_reg
(
dr
->
mapped_reg
,
dr
->
reg_width
)
>>
pos
)
&
1
;
return
(
gpio_read_raw_reg
(
dr
->
mapped_reg
,
dr
->
reg_width
)
>>
pos
)
&
1
;
}
}
EXPORT_SYMBOL_GPL
(
sh_pfc_read_bit
);
static
void
gpio_write_bit
(
struct
pinmux_data_reg
*
dr
,
void
sh_pfc_write_bit
(
struct
pinmux_data_reg
*
dr
,
unsigned
long
in_pos
,
unsigned
long
in_pos
,
unsigned
long
value
)
unsigned
long
value
)
{
{
unsigned
long
pos
;
unsigned
long
pos
;
...
@@ -166,8 +171,9 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
...
@@ -166,8 +171,9 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
gpio_write_raw_reg
(
dr
->
mapped_reg
,
dr
->
reg_width
,
dr
->
reg_shadow
);
gpio_write_raw_reg
(
dr
->
mapped_reg
,
dr
->
reg_width
,
dr
->
reg_shadow
);
}
}
EXPORT_SYMBOL_GPL
(
sh_pfc_write_bit
);
static
void
config_reg_helper
(
struct
pinmux_info
*
gpio
c
,
static
void
config_reg_helper
(
struct
sh_pfc
*
pf
c
,
struct
pinmux_cfg_reg
*
crp
,
struct
pinmux_cfg_reg
*
crp
,
unsigned
long
in_pos
,
unsigned
long
in_pos
,
void
__iomem
**
mapped_regp
,
void
__iomem
**
mapped_regp
,
...
@@ -176,7 +182,7 @@ static void config_reg_helper(struct pinmux_info *gpioc,
...
@@ -176,7 +182,7 @@ static void config_reg_helper(struct pinmux_info *gpioc,
{
{
int
k
;
int
k
;
*
mapped_regp
=
pfc_phys_to_virt
(
gpio
c
,
crp
->
reg
);
*
mapped_regp
=
pfc_phys_to_virt
(
pf
c
,
crp
->
reg
);
if
(
crp
->
field_width
)
{
if
(
crp
->
field_width
)
{
*
maskp
=
(
1
<<
crp
->
field_width
)
-
1
;
*
maskp
=
(
1
<<
crp
->
field_width
)
-
1
;
...
@@ -189,14 +195,14 @@ static void config_reg_helper(struct pinmux_info *gpioc,
...
@@ -189,14 +195,14 @@ static void config_reg_helper(struct pinmux_info *gpioc,
}
}
}
}
static
int
read_config_reg
(
struct
pinmux_info
*
gpio
c
,
static
int
read_config_reg
(
struct
sh_pfc
*
pf
c
,
struct
pinmux_cfg_reg
*
crp
,
struct
pinmux_cfg_reg
*
crp
,
unsigned
long
field
)
unsigned
long
field
)
{
{
void
__iomem
*
mapped_reg
;
void
__iomem
*
mapped_reg
;
unsigned
long
mask
,
pos
;
unsigned
long
mask
,
pos
;
config_reg_helper
(
gpio
c
,
crp
,
field
,
&
mapped_reg
,
&
mask
,
&
pos
);
config_reg_helper
(
pf
c
,
crp
,
field
,
&
mapped_reg
,
&
mask
,
&
pos
);
pr_debug
(
"read_reg: addr = %lx, field = %ld, "
pr_debug
(
"read_reg: addr = %lx, field = %ld, "
"r_width = %ld, f_width = %ld
\n
"
,
"r_width = %ld, f_width = %ld
\n
"
,
...
@@ -205,14 +211,14 @@ static int read_config_reg(struct pinmux_info *gpioc,
...
@@ -205,14 +211,14 @@ static int read_config_reg(struct pinmux_info *gpioc,
return
(
gpio_read_raw_reg
(
mapped_reg
,
crp
->
reg_width
)
>>
pos
)
&
mask
;
return
(
gpio_read_raw_reg
(
mapped_reg
,
crp
->
reg_width
)
>>
pos
)
&
mask
;
}
}
static
void
write_config_reg
(
struct
pinmux_info
*
gpio
c
,
static
void
write_config_reg
(
struct
sh_pfc
*
pf
c
,
struct
pinmux_cfg_reg
*
crp
,
struct
pinmux_cfg_reg
*
crp
,
unsigned
long
field
,
unsigned
long
value
)
unsigned
long
field
,
unsigned
long
value
)
{
{
void
__iomem
*
mapped_reg
;
void
__iomem
*
mapped_reg
;
unsigned
long
mask
,
pos
,
data
;
unsigned
long
mask
,
pos
,
data
;
config_reg_helper
(
gpio
c
,
crp
,
field
,
&
mapped_reg
,
&
mask
,
&
pos
);
config_reg_helper
(
pf
c
,
crp
,
field
,
&
mapped_reg
,
&
mask
,
&
pos
);
pr_debug
(
"write_reg addr = %lx, value = %ld, field = %ld, "
pr_debug
(
"write_reg addr = %lx, value = %ld, field = %ld, "
"r_width = %ld, f_width = %ld
\n
"
,
"r_width = %ld, f_width = %ld
\n
"
,
...
@@ -225,30 +231,30 @@ static void write_config_reg(struct pinmux_info *gpioc,
...
@@ -225,30 +231,30 @@ static void write_config_reg(struct pinmux_info *gpioc,
data
&=
mask
;
data
&=
mask
;
data
|=
value
;
data
|=
value
;
if
(
gpio
c
->
unlock_reg
)
if
(
pf
c
->
unlock_reg
)
gpio_write_raw_reg
(
pfc_phys_to_virt
(
gpioc
,
gpio
c
->
unlock_reg
),
gpio_write_raw_reg
(
pfc_phys_to_virt
(
pfc
,
pf
c
->
unlock_reg
),
32
,
~
data
);
32
,
~
data
);
gpio_write_raw_reg
(
mapped_reg
,
crp
->
reg_width
,
data
);
gpio_write_raw_reg
(
mapped_reg
,
crp
->
reg_width
,
data
);
}
}
static
int
setup_data_reg
(
struct
pinmux_info
*
gpio
c
,
unsigned
gpio
)
static
int
setup_data_reg
(
struct
sh_pfc
*
pf
c
,
unsigned
gpio
)
{
{
struct
pinmux_gpio
*
gpiop
=
&
gpio
c
->
gpios
[
gpio
];
struct
pinmux_gpio
*
gpiop
=
&
pf
c
->
gpios
[
gpio
];
struct
pinmux_data_reg
*
data_reg
;
struct
pinmux_data_reg
*
data_reg
;
int
k
,
n
;
int
k
,
n
;
if
(
!
enum_in_range
(
gpiop
->
enum_id
,
&
gpio
c
->
data
))
if
(
!
enum_in_range
(
gpiop
->
enum_id
,
&
pf
c
->
data
))
return
-
1
;
return
-
1
;
k
=
0
;
k
=
0
;
while
(
1
)
{
while
(
1
)
{
data_reg
=
gpio
c
->
data_regs
+
k
;
data_reg
=
pf
c
->
data_regs
+
k
;
if
(
!
data_reg
->
reg_width
)
if
(
!
data_reg
->
reg_width
)
break
;
break
;
data_reg
->
mapped_reg
=
pfc_phys_to_virt
(
gpio
c
,
data_reg
->
reg
);
data_reg
->
mapped_reg
=
pfc_phys_to_virt
(
pf
c
,
data_reg
->
reg
);
for
(
n
=
0
;
n
<
data_reg
->
reg_width
;
n
++
)
{
for
(
n
=
0
;
n
<
data_reg
->
reg_width
;
n
++
)
{
if
(
data_reg
->
enum_ids
[
n
]
==
gpiop
->
enum_id
)
{
if
(
data_reg
->
enum_ids
[
n
]
==
gpiop
->
enum_id
)
{
...
@@ -267,17 +273,17 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
...
@@ -267,17 +273,17 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
return
-
1
;
return
-
1
;
}
}
static
void
setup_data_regs
(
struct
pinmux_info
*
gpio
c
)
static
void
setup_data_regs
(
struct
sh_pfc
*
pf
c
)
{
{
struct
pinmux_data_reg
*
drp
;
struct
pinmux_data_reg
*
drp
;
int
k
;
int
k
;
for
(
k
=
gpioc
->
first_gpio
;
k
<=
gpio
c
->
last_gpio
;
k
++
)
for
(
k
=
pfc
->
first_gpio
;
k
<=
pf
c
->
last_gpio
;
k
++
)
setup_data_reg
(
gpio
c
,
k
);
setup_data_reg
(
pf
c
,
k
);
k
=
0
;
k
=
0
;
while
(
1
)
{
while
(
1
)
{
drp
=
gpio
c
->
data_regs
+
k
;
drp
=
pf
c
->
data_regs
+
k
;
if
(
!
drp
->
reg_width
)
if
(
!
drp
->
reg_width
)
break
;
break
;
...
@@ -288,23 +294,24 @@ static void setup_data_regs(struct pinmux_info *gpioc)
...
@@ -288,23 +294,24 @@ static void setup_data_regs(struct pinmux_info *gpioc)
}
}
}
}
static
int
get_data_reg
(
struct
pinmux_info
*
gpio
c
,
unsigned
gpio
,
int
sh_pfc_get_data_reg
(
struct
sh_pfc
*
pf
c
,
unsigned
gpio
,
struct
pinmux_data_reg
**
drp
,
int
*
bitp
)
struct
pinmux_data_reg
**
drp
,
int
*
bitp
)
{
{
struct
pinmux_gpio
*
gpiop
=
&
gpio
c
->
gpios
[
gpio
];
struct
pinmux_gpio
*
gpiop
=
&
pf
c
->
gpios
[
gpio
];
int
k
,
n
;
int
k
,
n
;
if
(
!
enum_in_range
(
gpiop
->
enum_id
,
&
gpio
c
->
data
))
if
(
!
enum_in_range
(
gpiop
->
enum_id
,
&
pf
c
->
data
))
return
-
1
;
return
-
1
;
k
=
(
gpiop
->
flags
&
PINMUX_FLAG_DREG
)
>>
PINMUX_FLAG_DREG_SHIFT
;
k
=
(
gpiop
->
flags
&
PINMUX_FLAG_DREG
)
>>
PINMUX_FLAG_DREG_SHIFT
;
n
=
(
gpiop
->
flags
&
PINMUX_FLAG_DBIT
)
>>
PINMUX_FLAG_DBIT_SHIFT
;
n
=
(
gpiop
->
flags
&
PINMUX_FLAG_DBIT
)
>>
PINMUX_FLAG_DBIT_SHIFT
;
*
drp
=
gpio
c
->
data_regs
+
k
;
*
drp
=
pf
c
->
data_regs
+
k
;
*
bitp
=
n
;
*
bitp
=
n
;
return
0
;
return
0
;
}
}
EXPORT_SYMBOL_GPL
(
sh_pfc_get_data_reg
);
static
int
get_config_reg
(
struct
pinmux_info
*
gpio
c
,
pinmux_enum_t
enum_id
,
static
int
get_config_reg
(
struct
sh_pfc
*
pf
c
,
pinmux_enum_t
enum_id
,
struct
pinmux_cfg_reg
**
crp
,
struct
pinmux_cfg_reg
**
crp
,
int
*
fieldp
,
int
*
valuep
,
int
*
fieldp
,
int
*
valuep
,
unsigned
long
**
cntp
)
unsigned
long
**
cntp
)
...
@@ -315,7 +322,7 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
...
@@ -315,7 +322,7 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
k
=
0
;
k
=
0
;
while
(
1
)
{
while
(
1
)
{
config_reg
=
gpio
c
->
cfg_regs
+
k
;
config_reg
=
pf
c
->
cfg_regs
+
k
;
r_width
=
config_reg
->
reg_width
;
r_width
=
config_reg
->
reg_width
;
f_width
=
config_reg
->
field_width
;
f_width
=
config_reg
->
field_width
;
...
@@ -350,15 +357,15 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
...
@@ -350,15 +357,15 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
return
-
1
;
return
-
1
;
}
}
static
int
get_gpio_enum_id
(
struct
pinmux_info
*
gpioc
,
unsigned
gpio
,
int
sh_pfc_gpio_to_enum
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
,
int
pos
,
int
pos
,
pinmux_enum_t
*
enum_idp
)
pinmux_enum_t
*
enum_idp
)
{
{
pinmux_enum_t
enum_id
=
gpio
c
->
gpios
[
gpio
].
enum_id
;
pinmux_enum_t
enum_id
=
pf
c
->
gpios
[
gpio
].
enum_id
;
pinmux_enum_t
*
data
=
gpio
c
->
gpio_data
;
pinmux_enum_t
*
data
=
pf
c
->
gpio_data
;
int
k
;
int
k
;
if
(
!
enum_in_range
(
enum_id
,
&
gpio
c
->
data
))
{
if
(
!
enum_in_range
(
enum_id
,
&
pf
c
->
data
))
{
if
(
!
enum_in_range
(
enum_id
,
&
gpio
c
->
mark
))
{
if
(
!
enum_in_range
(
enum_id
,
&
pf
c
->
mark
))
{
pr_err
(
"non data/mark enum_id for gpio %d
\n
"
,
gpio
);
pr_err
(
"non data/mark enum_id for gpio %d
\n
"
,
gpio
);
return
-
1
;
return
-
1
;
}
}
...
@@ -369,7 +376,7 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
...
@@ -369,7 +376,7 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
return
pos
+
1
;
return
pos
+
1
;
}
}
for
(
k
=
0
;
k
<
gpio
c
->
gpio_data_size
;
k
++
)
{
for
(
k
=
0
;
k
<
pf
c
->
gpio_data_size
;
k
++
)
{
if
(
data
[
k
]
==
enum_id
)
{
if
(
data
[
k
]
==
enum_id
)
{
*
enum_idp
=
data
[
k
+
1
];
*
enum_idp
=
data
[
k
+
1
];
return
k
+
1
;
return
k
+
1
;
...
@@ -379,11 +386,10 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
...
@@ -379,11 +386,10 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
pr_err
(
"cannot locate data/mark enum_id for gpio %d
\n
"
,
gpio
);
pr_err
(
"cannot locate data/mark enum_id for gpio %d
\n
"
,
gpio
);
return
-
1
;
return
-
1
;
}
}
EXPORT_SYMBOL_GPL
(
sh_pfc_gpio_to_enum
);
enum
{
GPIO_CFG_DRYRUN
,
GPIO_CFG_REQ
,
GPIO_CFG_FREE
};
int
sh_pfc_config_gpio
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
,
int
pinmux_type
,
int
cfg_mode
)
static
int
pinmux_config_gpio
(
struct
pinmux_info
*
gpioc
,
unsigned
gpio
,
int
pinmux_type
,
int
cfg_mode
)
{
{
struct
pinmux_cfg_reg
*
cr
=
NULL
;
struct
pinmux_cfg_reg
*
cr
=
NULL
;
pinmux_enum_t
enum_id
;
pinmux_enum_t
enum_id
;
...
@@ -398,19 +404,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
...
@@ -398,19 +404,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
break
;
break
;
case
PINMUX_TYPE_OUTPUT
:
case
PINMUX_TYPE_OUTPUT
:
range
=
&
gpio
c
->
output
;
range
=
&
pf
c
->
output
;
break
;
break
;
case
PINMUX_TYPE_INPUT
:
case
PINMUX_TYPE_INPUT
:
range
=
&
gpio
c
->
input
;
range
=
&
pf
c
->
input
;
break
;
break
;
case
PINMUX_TYPE_INPUT_PULLUP
:
case
PINMUX_TYPE_INPUT_PULLUP
:
range
=
&
gpio
c
->
input_pu
;
range
=
&
pf
c
->
input_pu
;
break
;
break
;
case
PINMUX_TYPE_INPUT_PULLDOWN
:
case
PINMUX_TYPE_INPUT_PULLDOWN
:
range
=
&
gpio
c
->
input_pd
;
range
=
&
pf
c
->
input_pd
;
break
;
break
;
default:
default:
...
@@ -422,7 +428,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
...
@@ -422,7 +428,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
field
=
0
;
field
=
0
;
value
=
0
;
value
=
0
;
while
(
1
)
{
while
(
1
)
{
pos
=
get_gpio_enum_id
(
gpio
c
,
gpio
,
pos
,
&
enum_id
);
pos
=
sh_pfc_gpio_to_enum
(
pf
c
,
gpio
,
pos
,
&
enum_id
);
if
(
pos
<=
0
)
if
(
pos
<=
0
)
goto
out_err
;
goto
out_err
;
...
@@ -430,7 +436,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
...
@@ -430,7 +436,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
break
;
break
;
/* first check if this is a function enum */
/* first check if this is a function enum */
in_range
=
enum_in_range
(
enum_id
,
&
gpio
c
->
function
);
in_range
=
enum_in_range
(
enum_id
,
&
pf
c
->
function
);
if
(
!
in_range
)
{
if
(
!
in_range
)
{
/* not a function enum */
/* not a function enum */
if
(
range
)
{
if
(
range
)
{
...
@@ -467,19 +473,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
...
@@ -467,19 +473,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
if
(
!
in_range
)
if
(
!
in_range
)
continue
;
continue
;
if
(
get_config_reg
(
gpio
c
,
enum_id
,
&
cr
,
if
(
get_config_reg
(
pf
c
,
enum_id
,
&
cr
,
&
field
,
&
value
,
&
cntp
)
!=
0
)
&
field
,
&
value
,
&
cntp
)
!=
0
)
goto
out_err
;
goto
out_err
;
switch
(
cfg_mode
)
{
switch
(
cfg_mode
)
{
case
GPIO_CFG_DRYRUN
:
case
GPIO_CFG_DRYRUN
:
if
(
!*
cntp
||
if
(
!*
cntp
||
(
read_config_reg
(
gpio
c
,
cr
,
field
)
!=
value
))
(
read_config_reg
(
pf
c
,
cr
,
field
)
!=
value
))
continue
;
continue
;
break
;
break
;
case
GPIO_CFG_REQ
:
case
GPIO_CFG_REQ
:
write_config_reg
(
gpio
c
,
cr
,
field
,
value
);
write_config_reg
(
pf
c
,
cr
,
field
,
value
);
*
cntp
=
*
cntp
+
1
;
*
cntp
=
*
cntp
+
1
;
break
;
break
;
...
@@ -493,89 +499,18 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
...
@@ -493,89 +499,18 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
out_err:
out_err:
return
-
1
;
return
-
1
;
}
}
EXPORT_SYMBOL_GPL
(
sh_pfc_config_gpio
);
static
DEFINE_SPINLOCK
(
gpio_lock
);
int
sh_pfc_set_direction
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
,
int
new_pinmux_type
)
static
struct
pinmux_info
*
chip_to_pinmux
(
struct
gpio_chip
*
chip
)
{
return
container_of
(
chip
,
struct
pinmux_info
,
chip
);
}
static
int
sh_gpio_request
(
struct
gpio_chip
*
chip
,
unsigned
offset
)
{
struct
pinmux_info
*
gpioc
=
chip_to_pinmux
(
chip
);
struct
pinmux_data_reg
*
dummy
;
unsigned
long
flags
;
int
i
,
ret
,
pinmux_type
;
ret
=
-
EINVAL
;
if
(
!
gpioc
)
goto
err_out
;
spin_lock_irqsave
(
&
gpio_lock
,
flags
);
if
((
gpioc
->
gpios
[
offset
].
flags
&
PINMUX_FLAG_TYPE
)
!=
PINMUX_TYPE_NONE
)
goto
err_unlock
;
/* setup pin function here if no data is associated with pin */
if
(
get_data_reg
(
gpioc
,
offset
,
&
dummy
,
&
i
)
!=
0
)
pinmux_type
=
PINMUX_TYPE_FUNCTION
;
else
pinmux_type
=
PINMUX_TYPE_GPIO
;
if
(
pinmux_type
==
PINMUX_TYPE_FUNCTION
)
{
if
(
pinmux_config_gpio
(
gpioc
,
offset
,
pinmux_type
,
GPIO_CFG_DRYRUN
)
!=
0
)
goto
err_unlock
;
if
(
pinmux_config_gpio
(
gpioc
,
offset
,
pinmux_type
,
GPIO_CFG_REQ
)
!=
0
)
BUG
();
}
gpioc
->
gpios
[
offset
].
flags
&=
~
PINMUX_FLAG_TYPE
;
gpioc
->
gpios
[
offset
].
flags
|=
pinmux_type
;
ret
=
0
;
err_unlock:
spin_unlock_irqrestore
(
&
gpio_lock
,
flags
);
err_out:
return
ret
;
}
static
void
sh_gpio_free
(
struct
gpio_chip
*
chip
,
unsigned
offset
)
{
struct
pinmux_info
*
gpioc
=
chip_to_pinmux
(
chip
);
unsigned
long
flags
;
int
pinmux_type
;
if
(
!
gpioc
)
return
;
spin_lock_irqsave
(
&
gpio_lock
,
flags
);
pinmux_type
=
gpioc
->
gpios
[
offset
].
flags
&
PINMUX_FLAG_TYPE
;
pinmux_config_gpio
(
gpioc
,
offset
,
pinmux_type
,
GPIO_CFG_FREE
);
gpioc
->
gpios
[
offset
].
flags
&=
~
PINMUX_FLAG_TYPE
;
gpioc
->
gpios
[
offset
].
flags
|=
PINMUX_TYPE_NONE
;
spin_unlock_irqrestore
(
&
gpio_lock
,
flags
);
}
static
int
pinmux_direction
(
struct
pinmux_info
*
gpioc
,
unsigned
gpio
,
int
new_pinmux_type
)
{
{
int
pinmux_type
;
int
pinmux_type
;
int
ret
=
-
EINVAL
;
int
ret
=
-
EINVAL
;
if
(
!
gpio
c
)
if
(
!
pf
c
)
goto
err_out
;
goto
err_out
;
pinmux_type
=
gpio
c
->
gpios
[
gpio
].
flags
&
PINMUX_FLAG_TYPE
;
pinmux_type
=
pf
c
->
gpios
[
gpio
].
flags
&
PINMUX_FLAG_TYPE
;
switch
(
pinmux_type
)
{
switch
(
pinmux_type
)
{
case
PINMUX_TYPE_GPIO
:
case
PINMUX_TYPE_GPIO
:
...
@@ -584,156 +519,60 @@ static int pinmux_direction(struct pinmux_info *gpioc,
...
@@ -584,156 +519,60 @@ static int pinmux_direction(struct pinmux_info *gpioc,
case
PINMUX_TYPE_INPUT
:
case
PINMUX_TYPE_INPUT
:
case
PINMUX_TYPE_INPUT_PULLUP
:
case
PINMUX_TYPE_INPUT_PULLUP
:
case
PINMUX_TYPE_INPUT_PULLDOWN
:
case
PINMUX_TYPE_INPUT_PULLDOWN
:
pinmux_config_gpio
(
gpio
c
,
gpio
,
pinmux_type
,
GPIO_CFG_FREE
);
sh_pfc_config_gpio
(
pf
c
,
gpio
,
pinmux_type
,
GPIO_CFG_FREE
);
break
;
break
;
default:
default:
goto
err_out
;
goto
err_out
;
}
}
if
(
pinmux_config_gpio
(
gpio
c
,
gpio
,
if
(
sh_pfc_config_gpio
(
pf
c
,
gpio
,
new_pinmux_type
,
new_pinmux_type
,
GPIO_CFG_DRYRUN
)
!=
0
)
GPIO_CFG_DRYRUN
)
!=
0
)
goto
err_out
;
goto
err_out
;
if
(
pinmux_config_gpio
(
gpio
c
,
gpio
,
if
(
sh_pfc_config_gpio
(
pf
c
,
gpio
,
new_pinmux_type
,
new_pinmux_type
,
GPIO_CFG_REQ
)
!=
0
)
GPIO_CFG_REQ
)
!=
0
)
BUG
();
BUG
();
gpio
c
->
gpios
[
gpio
].
flags
&=
~
PINMUX_FLAG_TYPE
;
pf
c
->
gpios
[
gpio
].
flags
&=
~
PINMUX_FLAG_TYPE
;
gpio
c
->
gpios
[
gpio
].
flags
|=
new_pinmux_type
;
pf
c
->
gpios
[
gpio
].
flags
|=
new_pinmux_type
;
ret
=
0
;
ret
=
0
;
err_out:
err_out:
return
ret
;
return
ret
;
}
}
EXPORT_SYMBOL_GPL
(
sh_pfc_set_direction
);
static
int
sh_gpio_direction_input
(
struct
gpio_chip
*
chip
,
unsigned
offset
)
int
register_sh_pfc
(
struct
sh_pfc
*
pfc
)
{
struct
pinmux_info
*
gpioc
=
chip_to_pinmux
(
chip
);
unsigned
long
flags
;
int
ret
;
spin_lock_irqsave
(
&
gpio_lock
,
flags
);
ret
=
pinmux_direction
(
gpioc
,
offset
,
PINMUX_TYPE_INPUT
);
spin_unlock_irqrestore
(
&
gpio_lock
,
flags
);
return
ret
;
}
static
void
sh_gpio_set_value
(
struct
pinmux_info
*
gpioc
,
unsigned
gpio
,
int
value
)
{
struct
pinmux_data_reg
*
dr
=
NULL
;
int
bit
=
0
;
if
(
!
gpioc
||
get_data_reg
(
gpioc
,
gpio
,
&
dr
,
&
bit
)
!=
0
)
BUG
();
else
gpio_write_bit
(
dr
,
bit
,
value
);
}
static
int
sh_gpio_direction_output
(
struct
gpio_chip
*
chip
,
unsigned
offset
,
int
value
)
{
{
struct
pinmux_info
*
gpioc
=
chip_to_pinmux
(
chip
);
int
(
*
initroutine
)(
struct
sh_pfc
*
)
=
NULL
;
unsigned
long
flags
;
int
ret
;
int
ret
;
sh_gpio_set_value
(
gpioc
,
offset
,
value
);
/*
spin_lock_irqsave
(
&
gpio_lock
,
flags
);
* Ensure that the type encoding fits
ret
=
pinmux_direction
(
gpioc
,
offset
,
PINMUX_TYPE_OUTPUT
);
*/
spin_unlock_irqrestore
(
&
gpio_lock
,
flags
);
BUILD_BUG_ON
(
PINMUX_FLAG_TYPE
>
((
1
<<
PINMUX_FLAG_DBIT_SHIFT
)
-
1
));
return
ret
;
}
static
int
sh_gpio_get_value
(
struct
pinmux_info
*
gpioc
,
unsigned
gpio
)
{
struct
pinmux_data_reg
*
dr
=
NULL
;
int
bit
=
0
;
if
(
!
gpioc
||
get_data_reg
(
gpioc
,
gpio
,
&
dr
,
&
bit
)
!=
0
)
return
-
EINVAL
;
return
gpio_read_bit
(
dr
,
bit
);
if
(
sh_pfc
)
}
return
-
EBUSY
;
static
int
sh_gpio_get
(
struct
gpio_chip
*
chip
,
unsigned
offset
)
{
return
sh_gpio_get_value
(
chip_to_pinmux
(
chip
),
offset
);
}
static
void
sh_gpio_set
(
struct
gpio_chip
*
chip
,
unsigned
offset
,
int
value
)
ret
=
pfc_ioremap
(
pfc
);
{
if
(
unlikely
(
ret
<
0
))
sh_gpio_set_value
(
chip_to_pinmux
(
chip
),
offset
,
value
);
}
static
int
sh_gpio_to_irq
(
struct
gpio_chip
*
chip
,
unsigned
offset
)
{
struct
pinmux_info
*
gpioc
=
chip_to_pinmux
(
chip
);
pinmux_enum_t
enum_id
;
pinmux_enum_t
*
enum_ids
;
int
i
,
k
,
pos
;
pos
=
0
;
enum_id
=
0
;
while
(
1
)
{
pos
=
get_gpio_enum_id
(
gpioc
,
offset
,
pos
,
&
enum_id
);
if
(
pos
<=
0
||
!
enum_id
)
break
;
for
(
i
=
0
;
i
<
gpioc
->
gpio_irq_size
;
i
++
)
{
enum_ids
=
gpioc
->
gpio_irq
[
i
].
enum_ids
;
for
(
k
=
0
;
enum_ids
[
k
];
k
++
)
{
if
(
enum_ids
[
k
]
==
enum_id
)
return
gpioc
->
gpio_irq
[
i
].
irq
;
}
}
}
return
-
ENOSYS
;
}
int
register_pinmux
(
struct
pinmux_info
*
pip
)
{
struct
gpio_chip
*
chip
=
&
pip
->
chip
;
int
ret
;
pr_info
(
"%s handling gpio %d -> %d
\n
"
,
pip
->
name
,
pip
->
first_gpio
,
pip
->
last_gpio
);
ret
=
pfc_ioremap
(
pip
);
if
(
ret
<
0
)
return
ret
;
return
ret
;
setup_data_regs
(
pip
);
spin_lock_init
(
&
pfc
->
lock
);
chip
->
request
=
sh_gpio_request
;
chip
->
free
=
sh_gpio_free
;
chip
->
direction_input
=
sh_gpio_direction_input
;
chip
->
get
=
sh_gpio_get
;
chip
->
direction_output
=
sh_gpio_direction_output
;
chip
->
set
=
sh_gpio_set
;
chip
->
to_irq
=
sh_gpio_to_irq
;
WARN_ON
(
pip
->
first_gpio
!=
0
);
/* needs testing */
chip
->
label
=
pip
->
name
;
setup_data_regs
(
pfc
);
chip
->
owner
=
THIS_MODULE
;
chip
->
base
=
pip
->
first_gpio
;
chip
->
ngpio
=
(
pip
->
last_gpio
-
pip
->
first_gpio
)
+
1
;
ret
=
gpiochip_add
(
chip
);
sh_pfc
=
pfc
;
if
(
ret
<
0
)
pr_info
(
"%s support registered
\n
"
,
pfc
->
name
);
pfc_iounmap
(
pip
);
return
ret
;
initroutine
=
symbol_request
(
sh_pfc_register_gpiochip
);
}
if
(
initroutine
)
{
(
*
initroutine
)(
pfc
);
symbol_put_addr
(
initroutine
);
}
int
unregister_pinmux
(
struct
pinmux_info
*
pip
)
return
0
;
{
pr_info
(
"%s deregistering
\n
"
,
pip
->
name
);
pfc_iounmap
(
pip
);
return
gpiochip_remove
(
&
pip
->
chip
);
}
}
drivers/sh/pfc/gpio.c
0 → 100644
View file @
a18d7f96
/*
* SuperH Pin Function Controller GPIO driver.
*
* Copyright (C) 2008 Magnus Damm
* Copyright (C) 2009 - 2012 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/platform_device.h>
struct
sh_pfc_chip
{
struct
sh_pfc
*
pfc
;
struct
gpio_chip
gpio_chip
;
};
static
struct
sh_pfc_chip
*
gpio_to_pfc_chip
(
struct
gpio_chip
*
gc
)
{
return
container_of
(
gc
,
struct
sh_pfc_chip
,
gpio_chip
);
}
static
struct
sh_pfc
*
gpio_to_pfc
(
struct
gpio_chip
*
gc
)
{
return
gpio_to_pfc_chip
(
gc
)
->
pfc
;
}
static
int
sh_gpio_request
(
struct
gpio_chip
*
gc
,
unsigned
offset
)
{
struct
sh_pfc
*
pfc
=
gpio_to_pfc
(
gc
);
struct
pinmux_data_reg
*
dummy
;
unsigned
long
flags
;
int
i
,
ret
,
pinmux_type
;
ret
=
-
EINVAL
;
if
(
!
pfc
)
goto
err_out
;
spin_lock_irqsave
(
&
pfc
->
lock
,
flags
);
if
((
pfc
->
gpios
[
offset
].
flags
&
PINMUX_FLAG_TYPE
)
!=
PINMUX_TYPE_NONE
)
goto
err_unlock
;
/* setup pin function here if no data is associated with pin */
if
(
sh_pfc_get_data_reg
(
pfc
,
offset
,
&
dummy
,
&
i
)
!=
0
)
pinmux_type
=
PINMUX_TYPE_FUNCTION
;
else
pinmux_type
=
PINMUX_TYPE_GPIO
;
if
(
pinmux_type
==
PINMUX_TYPE_FUNCTION
)
{
if
(
sh_pfc_config_gpio
(
pfc
,
offset
,
pinmux_type
,
GPIO_CFG_DRYRUN
)
!=
0
)
goto
err_unlock
;
if
(
sh_pfc_config_gpio
(
pfc
,
offset
,
pinmux_type
,
GPIO_CFG_REQ
)
!=
0
)
BUG
();
}
pfc
->
gpios
[
offset
].
flags
&=
~
PINMUX_FLAG_TYPE
;
pfc
->
gpios
[
offset
].
flags
|=
pinmux_type
;
ret
=
0
;
err_unlock:
spin_unlock_irqrestore
(
&
pfc
->
lock
,
flags
);
err_out:
return
ret
;
}
static
void
sh_gpio_free
(
struct
gpio_chip
*
gc
,
unsigned
offset
)
{
struct
sh_pfc
*
pfc
=
gpio_to_pfc
(
gc
);
unsigned
long
flags
;
int
pinmux_type
;
if
(
!
pfc
)
return
;
spin_lock_irqsave
(
&
pfc
->
lock
,
flags
);
pinmux_type
=
pfc
->
gpios
[
offset
].
flags
&
PINMUX_FLAG_TYPE
;
sh_pfc_config_gpio
(
pfc
,
offset
,
pinmux_type
,
GPIO_CFG_FREE
);
pfc
->
gpios
[
offset
].
flags
&=
~
PINMUX_FLAG_TYPE
;
pfc
->
gpios
[
offset
].
flags
|=
PINMUX_TYPE_NONE
;
spin_unlock_irqrestore
(
&
pfc
->
lock
,
flags
);
}
static
int
sh_gpio_direction_input
(
struct
gpio_chip
*
gc
,
unsigned
offset
)
{
struct
sh_pfc
*
pfc
=
gpio_to_pfc
(
gc
);
unsigned
long
flags
;
int
ret
;
spin_lock_irqsave
(
&
pfc
->
lock
,
flags
);
ret
=
sh_pfc_set_direction
(
pfc
,
offset
,
PINMUX_TYPE_INPUT
);
spin_unlock_irqrestore
(
&
pfc
->
lock
,
flags
);
return
ret
;
}
static
void
sh_gpio_set_value
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
,
int
value
)
{
struct
pinmux_data_reg
*
dr
=
NULL
;
int
bit
=
0
;
if
(
!
pfc
||
sh_pfc_get_data_reg
(
pfc
,
gpio
,
&
dr
,
&
bit
)
!=
0
)
BUG
();
else
sh_pfc_write_bit
(
dr
,
bit
,
value
);
}
static
int
sh_gpio_direction_output
(
struct
gpio_chip
*
gc
,
unsigned
offset
,
int
value
)
{
struct
sh_pfc
*
pfc
=
gpio_to_pfc
(
gc
);
unsigned
long
flags
;
int
ret
;
sh_gpio_set_value
(
pfc
,
offset
,
value
);
spin_lock_irqsave
(
&
pfc
->
lock
,
flags
);
ret
=
sh_pfc_set_direction
(
pfc
,
offset
,
PINMUX_TYPE_OUTPUT
);
spin_unlock_irqrestore
(
&
pfc
->
lock
,
flags
);
return
ret
;
}
static
int
sh_gpio_get_value
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
)
{
struct
pinmux_data_reg
*
dr
=
NULL
;
int
bit
=
0
;
if
(
!
pfc
||
sh_pfc_get_data_reg
(
pfc
,
gpio
,
&
dr
,
&
bit
)
!=
0
)
return
-
EINVAL
;
return
sh_pfc_read_bit
(
dr
,
bit
);
}
static
int
sh_gpio_get
(
struct
gpio_chip
*
gc
,
unsigned
offset
)
{
return
sh_gpio_get_value
(
gpio_to_pfc
(
gc
),
offset
);
}
static
void
sh_gpio_set
(
struct
gpio_chip
*
gc
,
unsigned
offset
,
int
value
)
{
sh_gpio_set_value
(
gpio_to_pfc
(
gc
),
offset
,
value
);
}
static
int
sh_gpio_to_irq
(
struct
gpio_chip
*
gc
,
unsigned
offset
)
{
struct
sh_pfc
*
pfc
=
gpio_to_pfc
(
gc
);
pinmux_enum_t
enum_id
;
pinmux_enum_t
*
enum_ids
;
int
i
,
k
,
pos
;
pos
=
0
;
enum_id
=
0
;
while
(
1
)
{
pos
=
sh_pfc_gpio_to_enum
(
pfc
,
offset
,
pos
,
&
enum_id
);
if
(
pos
<=
0
||
!
enum_id
)
break
;
for
(
i
=
0
;
i
<
pfc
->
gpio_irq_size
;
i
++
)
{
enum_ids
=
pfc
->
gpio_irq
[
i
].
enum_ids
;
for
(
k
=
0
;
enum_ids
[
k
];
k
++
)
{
if
(
enum_ids
[
k
]
==
enum_id
)
return
pfc
->
gpio_irq
[
i
].
irq
;
}
}
}
return
-
ENOSYS
;
}
static
void
sh_pfc_gpio_setup
(
struct
sh_pfc_chip
*
chip
)
{
struct
sh_pfc
*
pfc
=
chip
->
pfc
;
struct
gpio_chip
*
gc
=
&
chip
->
gpio_chip
;
gc
->
request
=
sh_gpio_request
;
gc
->
free
=
sh_gpio_free
;
gc
->
direction_input
=
sh_gpio_direction_input
;
gc
->
get
=
sh_gpio_get
;
gc
->
direction_output
=
sh_gpio_direction_output
;
gc
->
set
=
sh_gpio_set
;
gc
->
to_irq
=
sh_gpio_to_irq
;
WARN_ON
(
pfc
->
first_gpio
!=
0
);
/* needs testing */
gc
->
label
=
pfc
->
name
;
gc
->
owner
=
THIS_MODULE
;
gc
->
base
=
pfc
->
first_gpio
;
gc
->
ngpio
=
(
pfc
->
last_gpio
-
pfc
->
first_gpio
)
+
1
;
}
int
sh_pfc_register_gpiochip
(
struct
sh_pfc
*
pfc
)
{
struct
sh_pfc_chip
*
chip
;
int
ret
;
chip
=
kzalloc
(
sizeof
(
struct
sh_pfc_chip
),
GFP_KERNEL
);
if
(
unlikely
(
!
chip
))
return
-
ENOMEM
;
chip
->
pfc
=
pfc
;
sh_pfc_gpio_setup
(
chip
);
ret
=
gpiochip_add
(
&
chip
->
gpio_chip
);
if
(
unlikely
(
ret
<
0
))
kfree
(
chip
);
pr_info
(
"%s handling gpio %d -> %d
\n
"
,
pfc
->
name
,
pfc
->
first_gpio
,
pfc
->
last_gpio
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
sh_pfc_register_gpiochip
);
static
int
sh_pfc_gpio_match
(
struct
gpio_chip
*
gc
,
void
*
data
)
{
return
!!
strstr
(
gc
->
label
,
data
);
}
static
int
__devinit
sh_pfc_gpio_probe
(
struct
platform_device
*
pdev
)
{
struct
sh_pfc_chip
*
chip
;
struct
gpio_chip
*
gc
;
gc
=
gpiochip_find
(
"_pfc"
,
sh_pfc_gpio_match
);
if
(
unlikely
(
!
gc
))
{
pr_err
(
"Cant find gpio chip
\n
"
);
return
-
ENODEV
;
}
chip
=
gpio_to_pfc_chip
(
gc
);
platform_set_drvdata
(
pdev
,
chip
);
pr_info
(
"attaching to GPIO chip %s
\n
"
,
chip
->
pfc
->
name
);
return
0
;
}
static
int
__devexit
sh_pfc_gpio_remove
(
struct
platform_device
*
pdev
)
{
struct
sh_pfc_chip
*
chip
=
platform_get_drvdata
(
pdev
);
int
ret
;
ret
=
gpiochip_remove
(
&
chip
->
gpio_chip
);
if
(
unlikely
(
ret
<
0
))
return
ret
;
kfree
(
chip
);
return
0
;
}
static
struct
platform_driver
sh_pfc_gpio_driver
=
{
.
probe
=
sh_pfc_gpio_probe
,
.
remove
=
__devexit_p
(
sh_pfc_gpio_remove
),
.
driver
=
{
.
name
=
KBUILD_MODNAME
,
.
owner
=
THIS_MODULE
,
},
};
static
struct
platform_device
sh_pfc_gpio_device
=
{
.
name
=
KBUILD_MODNAME
,
.
id
=
-
1
,
};
static
int
__init
sh_pfc_gpio_init
(
void
)
{
int
rc
;
rc
=
platform_driver_register
(
&
sh_pfc_gpio_driver
);
if
(
likely
(
!
rc
))
{
rc
=
platform_device_register
(
&
sh_pfc_gpio_device
);
if
(
unlikely
(
rc
))
platform_driver_unregister
(
&
sh_pfc_gpio_driver
);
}
return
rc
;
}
static
void
__exit
sh_pfc_gpio_exit
(
void
)
{
platform_device_unregister
(
&
sh_pfc_gpio_device
);
platform_driver_unregister
(
&
sh_pfc_gpio_driver
);
}
module_init
(
sh_pfc_gpio_init
);
module_exit
(
sh_pfc_gpio_exit
);
MODULE_AUTHOR
(
"Magnus Damm, Paul Mundt"
);
MODULE_DESCRIPTION
(
"GPIO driver for SuperH pin function controller"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:pfc-gpio"
);
include/linux/sh_pfc.h
View file @
a18d7f96
...
@@ -16,17 +16,18 @@
...
@@ -16,17 +16,18 @@
typedef
unsigned
short
pinmux_enum_t
;
typedef
unsigned
short
pinmux_enum_t
;
typedef
unsigned
short
pinmux_flag_t
;
typedef
unsigned
short
pinmux_flag_t
;
#define PINMUX_TYPE_NONE 0
enum
{
#define PINMUX_TYPE_FUNCTION 1
PINMUX_TYPE_NONE
,
#define PINMUX_TYPE_GPIO 2
#define PINMUX_TYPE_OUTPUT 3
PINMUX_TYPE_FUNCTION
,
#define PINMUX_TYPE_INPUT 4
PINMUX_TYPE_GPIO
,
#define PINMUX_TYPE_INPUT_PULLUP 5
PINMUX_TYPE_OUTPUT
,
#define PINMUX_TYPE_INPUT_PULLDOWN 6
PINMUX_TYPE_INPUT
,
PINMUX_TYPE_INPUT_PULLUP
,
#define PINMUX_FLAG_TYPE (0x7)
PINMUX_TYPE_INPUT_PULLDOWN
,
#define PINMUX_FLAG_WANT_PULLUP (1 << 3)
#define PINMUX_FLAG_WANT_PULLDOWN (1 << 4)
PINMUX_FLAG_TYPE
,
/* must be last */
};
#define PINMUX_FLAG_DBIT_SHIFT 5
#define PINMUX_FLAG_DBIT_SHIFT 5
#define PINMUX_FLAG_DBIT (0x1f << PINMUX_FLAG_DBIT_SHIFT)
#define PINMUX_FLAG_DBIT (0x1f << PINMUX_FLAG_DBIT_SHIFT)
...
@@ -38,7 +39,9 @@ struct pinmux_gpio {
...
@@ -38,7 +39,9 @@ struct pinmux_gpio {
pinmux_flag_t
flags
;
pinmux_flag_t
flags
;
};
};
#define PINMUX_GPIO(gpio, data_or_mark) [gpio] = { data_or_mark }
#define PINMUX_GPIO(gpio, data_or_mark) \
[gpio] = { .enum_id = data_or_mark, .flags = PINMUX_TYPE_NONE }
#define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0
#define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0
struct
pinmux_cfg_reg
{
struct
pinmux_cfg_reg
{
...
@@ -89,7 +92,7 @@ struct pfc_window {
...
@@ -89,7 +92,7 @@ struct pfc_window {
unsigned
long
size
;
unsigned
long
size
;
};
};
struct
pinmux_info
{
struct
sh_pfc
{
char
*
name
;
char
*
name
;
pinmux_enum_t
reserved_id
;
pinmux_enum_t
reserved_id
;
struct
pinmux_range
data
;
struct
pinmux_range
data
;
...
@@ -112,17 +115,44 @@ struct pinmux_info {
...
@@ -112,17 +115,44 @@ struct pinmux_info {
struct
pinmux_irq
*
gpio_irq
;
struct
pinmux_irq
*
gpio_irq
;
unsigned
int
gpio_irq_size
;
unsigned
int
gpio_irq_size
;
spinlock_t
lock
;
struct
resource
*
resource
;
struct
resource
*
resource
;
unsigned
int
num_resources
;
unsigned
int
num_resources
;
struct
pfc_window
*
window
;
struct
pfc_window
*
window
;
unsigned
long
unlock_reg
;
unsigned
long
unlock_reg
;
struct
gpio_chip
chip
;
};
};
int
register_pinmux
(
struct
pinmux_info
*
pip
);
/* XXX compat for now */
int
unregister_pinmux
(
struct
pinmux_info
*
pip
);
#define pinmux_info sh_pfc
/* drivers/sh/pfc/gpio.c */
int
sh_pfc_register_gpiochip
(
struct
sh_pfc
*
pfc
);
/* drivers/sh/pfc/core.c */
int
register_sh_pfc
(
struct
sh_pfc
*
pfc
);
int
sh_pfc_read_bit
(
struct
pinmux_data_reg
*
dr
,
unsigned
long
in_pos
);
void
sh_pfc_write_bit
(
struct
pinmux_data_reg
*
dr
,
unsigned
long
in_pos
,
unsigned
long
value
);
int
sh_pfc_get_data_reg
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
,
struct
pinmux_data_reg
**
drp
,
int
*
bitp
);
int
sh_pfc_gpio_to_enum
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
,
int
pos
,
pinmux_enum_t
*
enum_idp
);
int
sh_pfc_config_gpio
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
,
int
pinmux_type
,
int
cfg_mode
);
int
sh_pfc_set_direction
(
struct
sh_pfc
*
pfc
,
unsigned
gpio
,
int
new_pinmux_type
);
/* xxx */
static
inline
int
register_pinmux
(
struct
pinmux_info
*
pip
)
{
struct
sh_pfc
*
pfc
=
pip
;
return
register_sh_pfc
(
pfc
);
}
enum
{
GPIO_CFG_DRYRUN
,
GPIO_CFG_REQ
,
GPIO_CFG_FREE
};
/* helper macro for port */
/* helper macro for port */
#define PORT_1(fn, pfx, sfx) fn(pfx, sfx)
#define PORT_1(fn, pfx, sfx) fn(pfx, sfx)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment