Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Simple PCIe FMC carrier SPEC - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Simple PCIe FMC carrier SPEC - Software
Commits
234c680b
Commit
234c680b
authored
Oct 09, 2012
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
spec: implement gpio_config
Signed-off-by:
Alessandro Rubini
<
rubini@gnudd.com
>
parent
e8b0492f
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
117 additions
and
21 deletions
+117
-21
spec-fmc.c
kernel/spec-fmc.c
+113
-21
spec-pci.c
kernel/spec-pci.c
+4
-0
No files found.
kernel/spec-fmc.c
View file @
234c680b
...
...
@@ -11,6 +11,7 @@
#include <linux/fmc.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/gpio.h>
#include <linux/fmc-sdb.h>
#include "spec.h"
...
...
@@ -112,27 +113,7 @@ static int spec_irq_request(struct fmc_device *fmc, irq_handler_t handler,
gennum_writel
(
spec
,
value
,
GNPPCI_MSI_CONTROL
);
}
/* Enable gpio interrupts:
* gpio6: tp8: output low
* gpio7: tp7: input (was: interrupt, raising edge)
* gpio8: IRQ1 from FPGA: interrupt, raising edge
* gpio9: IRQ0 from FPGA: interrupt, raising edge
* gpio10: tp6: output low
* gpio11: tp5: input (was: interrupt, raising edge)
*/
/* bypass = alternate function */
gennum_mask_val
(
spec
,
0xfc0
,
0x00
,
GNGPIO_BYPASS_MODE
);
/* direction 0 = output */
gennum_mask_val
(
spec
,
0x440
,
0x000
,
GNGPIO_DIRECTION_MODE
);
gennum_mask_val
(
spec
,
0xb80
,
0xb80
,
GNGPIO_DIRECTION_MODE
);
gennum_mask_val
(
spec
,
0x440
,
0x440
,
GNGPIO_OUTPUT_ENABLE
);
gennum_mask_val
(
spec
,
0x300
,
0x000
,
GNGPIO_INT_TYPE
);
/* 0 = edge */
gennum_mask_val
(
spec
,
0x300
,
0x300
,
GNGPIO_INT_VALUE
);
/* 1 = raising */
gennum_mask_val
(
spec
,
0x300
,
0x000
,
GNGPIO_INT_ON_ANY
);
gennum_writel
(
spec
,
0x300
,
GNGPIO_INT_MASK_CLR
);
/* enable */
/* Interrupts are enabled by the driver, with gpio_config() */
return
0
;
}
...
...
@@ -157,6 +138,116 @@ static int spec_irq_free(struct fmc_device *fmc)
return
0
;
}
/* This is the mapping from virtual GPIO pin numbers to raw gpio numbers */
struct
{
int
virtual
;
int
raw
;
}
spec_gpio_map
[]
=
{
/* 0: TCK */
/* 1: TMS */
/* 2: TDO */
/* 3: TDI */
/* 4: SDA */
/* 5: SCL */
/* 6: TP8 */
{
FMC_GPIO_TP
(
3
),
FMC_GPIO_RAW
(
6
)},
/* 7: TP7 */
{
FMC_GPIO_TP
(
2
),
FMC_GPIO_RAW
(
7
)},
/* 8: IRQ */
{
FMC_GPIO_IRQ
(
0
),
FMC_GPIO_RAW
(
8
)},
/* 9: IRQ */
{
FMC_GPIO_IRQ
(
1
),
FMC_GPIO_RAW
(
9
)},
/* 10: TP6 */
{
FMC_GPIO_TP
(
1
),
FMC_GPIO_RAW
(
10
)},
/* 11: TP5 */
{
FMC_GPIO_TP
(
0
),
FMC_GPIO_RAW
(
11
)},
/* 12: flash_cs, 13: spri_din, 14: bootsel1, 15: bootsel0 */
};
static
int
spec_map_pin
(
int
virtual
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
spec_gpio_map
);
i
++
)
if
(
spec_gpio_map
[
i
].
virtual
==
virtual
)
return
spec_gpio_map
[
i
].
raw
;
return
-
ENOENT
;
}
static
int
spec_cfg_pin
(
struct
fmc_device
*
fmc
,
int
pin
,
int
mode
,
int
imode
)
{
struct
spec_dev
*
spec
=
fmc
->
carrier_data
;
int
ret
=
0
;
int
bit
=
(
1
<<
pin
);
if
(
pin
<
0
||
pin
>
15
)
return
-
ENODEV
;
if
(
mode
&
(
GPIOF_OPEN_DRAIN
|
GPIOF_OPEN_SOURCE
))
return
-
EINVAL
;
if
(
mode
&
GPIOF_DIR_IN
)
{
/* 1 = input */
gennum_mask_val
(
spec
,
bit
,
bit
,
GNGPIO_DIRECTION_MODE
);
gennum_mask_val
(
spec
,
bit
,
bit
,
GNGPIO_OUTPUT_ENABLE
);
ret
=
!!
(
gennum_readl
(
spec
,
GNGPIO_INPUT_VALUE
)
&
bit
);
}
else
{
if
(
mode
&
GPIOF_INIT_HIGH
)
gennum_mask_val
(
spec
,
bit
,
bit
,
GNGPIO_OUTPUT_VALUE
);
else
gennum_mask_val
(
spec
,
bit
,
0
,
GNGPIO_OUTPUT_VALUE
);
gennum_mask_val
(
spec
,
bit
,
0
,
GNGPIO_DIRECTION_MODE
);
}
/* Then, interrupt configuration, if needed */
if
(
!
(
imode
&
IRQF_TRIGGER_MASK
))
{
gennum_writel
(
spec
,
bit
,
GNGPIO_INT_MASK_SET
);
/* disable */
return
ret
;
}
if
(
imode
&
(
IRQF_TRIGGER_HIGH
|
IRQF_TRIGGER_RISING
))
gennum_mask_val
(
spec
,
bit
,
bit
,
GNGPIO_INT_VALUE
);
else
gennum_mask_val
(
spec
,
bit
,
0
,
GNGPIO_INT_VALUE
);
if
(
imode
&
(
IRQF_TRIGGER_HIGH
|
IRQF_TRIGGER_LOW
))
gennum_mask_val
(
spec
,
bit
,
bit
,
GNGPIO_INT_TYPE
);
else
gennum_mask_val
(
spec
,
bit
,
0
,
GNGPIO_INT_TYPE
);
gennum_mask_val
(
spec
,
bit
,
0
,
GNGPIO_INT_ON_ANY
);
/* me lazy */
gennum_writel
(
spec
,
bit
,
GNGPIO_INT_MASK_CLR
);
/* enable */
return
ret
;
}
static
int
spec_gpio_config
(
struct
fmc_device
*
fmc
,
struct
fmc_gpio
*
gpio
,
int
ngpio
)
{
int
i
,
done
=
0
,
retval
=
0
;
for
(
;
ngpio
;
gpio
++
,
ngpio
--
)
{
if
(
gpio
->
carrier_name
&&
strcmp
(
gpio
->
carrier_name
,
"SPEC"
))
{
/* The array may setup raw pins for various carriers */
continue
;
}
if
(
gpio
->
carrier_name
)
{
/* so, it's ours */
gpio
->
_gpio
=
gpio
->
gpio
;
}
else
if
(
!
gpio
->
_gpio
)
{
/* virtual but not mapped (or poor gpio0) */
i
=
spec_map_pin
(
gpio
->
gpio
);
if
(
i
<
0
)
return
i
;
gpio
->
_gpio
=
i
;
}
i
=
spec_cfg_pin
(
fmc
,
gpio
->
_gpio
,
gpio
->
mode
,
gpio
->
irqmode
);
if
(
i
<
0
)
return
i
;
retval
+=
i
;
/* may be the input value */
done
++
;
}
if
(
!
done
)
return
-
ENODEV
;
return
retval
;
}
/* The engines for this live in spec-i2c.c, we only shape arguments */
static
int
spec_read_ee
(
struct
fmc_device
*
fmc
,
int
pos
,
void
*
data
,
int
len
)
{
...
...
@@ -180,6 +271,7 @@ static struct fmc_operations spec_fmc_operations = {
.
irq_request
=
spec_irq_request
,
.
irq_ack
=
spec_irq_ack
,
.
irq_free
=
spec_irq_free
,
.
gpio_config
=
spec_gpio_config
,
.
read_ee
=
spec_read_ee
,
.
write_ee
=
spec_write_ee
,
};
...
...
kernel/spec-pci.c
View file @
234c680b
...
...
@@ -127,6 +127,10 @@ static int __devinit spec_probe(struct pci_dev *pdev,
if
(
ret
)
goto
out_unmap
;
/* Put our 6 pins to a sane state (4 test points, 2 from FPGA) */
gennum_mask_val
(
spec
,
0xfc0
,
0x000
,
GNGPIO_BYPASS_MODE
);
/* no AF */
gennum_mask_val
(
spec
,
0xfc0
,
0xfc0
,
GNGPIO_DIRECTION_MODE
);
/* input */
gennum_writel
(
spec
,
0xffff
,
GNGPIO_INT_MASK_SET
);
/* disable */
/* Load the golden FPGA binary to read the eeprom */
ret
=
spec_load_fpga_file
(
spec
,
spec_fw_name
);
...
...
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