Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /********************************************************************
- * Description: sunxi_gpio.c
- * Driver for the sunxi GPIO pins
- ********************************************************************/
- #include "rtapi.h" /* RTAPI realtime OS API */
- #include "rtapi_bitops.h"
- #include "rtapi_app.h" /* RTAPI realtime module decls */
- /* this also includes config.h */
- #include "hal.h" /* HAL public API decls */
- #if !defined(BUILD_SYS_USER_DSO)
- #error "This driver is for usermode threads only"
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <errno.h>
- /* Allwinner A1X port mode numbers */
- #define SUN5I_GPIO_A 0
- #define SUN5I_GPIO_B 1
- #define SUN5I_GPIO_C 2
- #define SUN5I_GPIO_D 3
- #define SUN5I_GPIO_E 4
- #define SUN5I_GPIO_F 5
- #define SUN5I_GPIO_G 6
- #define SUN5I_GPIO_H 7
- #define SUN5I_GPIO_I 8
- /* PA registers */
- #define SUN5I_PA_CFG0(n) ((n * 0x24) + 0x00)
- #define SUN5I_PA_CFG1(n) ((n * 0x24) + 0x04)
- #define SUN5I_PA_CFG2(n) ((n * 0x24) + 0x08)
- #define SUN5I_PA_CFG3(n) ((n * 0x24) + 0x0C)
- #define SUN5I_PA_DAT(n) ((n * 0x24) + 0x10)
- #define SUN5I_PA_DRV0(n) ((n * 0x24) + 0x14)
- #define SUN5I_PA_DRV1(n) ((n * 0x24) + 0x18)
- #define SUN5I_PA_PUL0(n) ((n * 0x24) + 0x1C)
- #define SUN5I_PA_PUL1(n) ((n * 0x24) + 0x20)
- /* PIO data registers */
- #define PIO_PG_DATA_OFFSET ((SUN5I_GPIO_G * 0x24) + 0x10)
- #define PIO_PG_CFG1_OFFSET ((SUN5I_GPIO_G * 0x24) + 0x04)
- /* Allwinner A1X gpio mode numbers */
- #define SUN5I_GPIO_INPUT 0
- #define SUN5I_GPIO_OUTPUT 1
- /* PIO controller defines */
- #define PIO_BASE_ADDRESS (0x01c20800)
- #define PIO_RANGE_SIZE (0x400)
- /* Set GPIO pin mode (input, output, etc) */
- /* GPIO port has 4 cfg 32bit registers (8 pins each) */
- /* First port cfg register addr = port_num * 0x24
- #define SUNXI_SET_GPIO_MODE(addr, port, pin, mode) ({ \
- __u32 reg_val = 0; \
- __u32 pin_idx = pin >> 3; \
- void *raddr = addr + (((port)-1)*0x24 + ((pin_idx)<<2) + 0x00); \
- reg_val = readl(raddr); \
- reg_val &= ~(0x07 << (((pin - (pin_idx<<3))<<2))); \
- reg_val |= mode << (((pin - (pin_idx<<3))<<2)); \
- writel(reg_val, raddr); \
- }) */
- static unsigned int mmap_Base = 0;
- static unsigned char rev1_gpios[] = {0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, 24, 25};
- static unsigned char rev1_pins[] = {3, 5, 7, 26, 24, 21, 19, 23, 8, 10, 11, 12, 13, 15, 16, 18, 22};
- static int npins;
- static int mem_fd;
- // I/O access
- volatile unsigned *gpio;
- MODULE_AUTHOR("uMinded");
- MODULE_DESCRIPTION("Driver for sunxi GPIO pins");
- MODULE_LICENSE("GPL");
- // port direction bits, 1=output
- static char *dir = "-1"; // all output
- RTAPI_MP_STRING(dir, "port direction, 1=output");
- static unsigned dir_map;
- // exclude pins from usage
- static char *exclude = "0"; // all used
- RTAPI_MP_STRING(exclude, "exclude pins, 1=dont use");
- static unsigned exclude_map;
- static int comp_id; /* component ID */
- static unsigned char *pins, *gpios;
- hal_bit_t **port_data;
- static void write_port(void *arg, long period);
- void SUNXI_SET_GPIO_MODE(addr, port, pin, mode) {
- __u32 reg_val = 0;
- __u32 pin_idx = pin >> 3;
- void *raddr = addr + (((port)-1)*0x24 + ((pin_idx)<<2) + 0x00);
- reg_val = *(unsigned int*)(mmap_Base + raddr);
- reg_val &= ~(0x07 << (((pin - (pin_idx<<3))<<2)));
- reg_val |= mode << (((pin - (pin_idx<<3))<<2));
- *(unsigned int*)(mmap_Base + raddr) = reg_val;
- }
- int init_base(unsigned long port_base)
- {
- int fd;
- unsigned int addr_start, addr_offset, addr;
- unsigned int PageSize, PageMask;
- void* address;
- rtapi_print("SUN5I_GPIO: Attempting to access /dev/mem\n");
- fd = open("/dev/mem", O_RDWR);
- if(fd < 0) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: /dev/mem failed: %d - %s\n", errno, strerror(errno));
- return -ENOMEM;;
- }
- PageSize = sysconf(_SC_PAGESIZE);
- PageMask = (~(PageSize-1));
- addr_start = port_base & PageMask;
- addr_offset = port_base & ~PageMask;
- rtapi_print("SUN5I_GPIO: Attempting to run mmap\n");
- address = (void*)mmap(0, PageSize*2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, addr_start);
- if(address == MAP_FAILED) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: mmap failed: %d - %s\n", errno, strerror(errno));
- return -ENOMEM;;
- }
- mmap_Base = (unsigned int)address;
- mmap_Base += addr_offset;
- close(fd);
- return 0;
- }
- int rtapi_app_main(void) {
- // __iomem *GADDR = ioremap(PIO_BASE_ADDRESS, PIO_RANGE_SIZE);
- rtapi_print("SUN5I_GPIO: comp_id: %i\n", comp_id);
- int n, retval = 0;
- int rev, pinno;
- char *endptr;
- pins = rev1_pins;
- gpios = rev1_gpios;
- npins = sizeof(rev1_pins);
- rtapi_print("SUN5I_GPIO: Loading gloabal PIO address pointer\n");
- if( init_base(PIO_BASE_ADDRESS) ) {
- printf("init_base(SUNXI_TIMER_BASE) ERROR\n");
- exit(-1);
- }
- port_data = hal_malloc(npins * sizeof(void *));
- if (port_data == 0) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: ERROR: hal_malloc() failed\n");
- hal_exit(comp_id);
- return -1;
- }
- if (dir == 0) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: ERROR: no config string\n");
- return -1;
- }
- dir_map = strtoul(dir, &endptr, 0);
- if (*endptr) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: dir=%s - trailing garbage: '%s'\n", dir, endptr);
- return -1;
- }
- if (exclude == 0) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: ERROR: no exclude string\n");
- return -1;
- }
- exclude_map = strtoul(exclude, &endptr,0);
- if (*endptr) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: exclude=%s - trailing garbage: '%s'\n", exclude, endptr);
- return -1;
- }
- /*
- * Set Up the HAL component structure
- */
- comp_id = hal_init("sunxi_gpio");
- if (comp_id < 0) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: ERROR: hal_init() failed\n");
- return -1;
- }
- rtapi_print("SUN5I_GPIO: comp_id: %i\n", comp_id);
- rtapi_print("SUN5I_GPIO: Set the GPIO pin as an output\n");
- //SUNXI_SET_GPIO_MODE(mmap_Base, SUN5I_GPIO_G, 9, SUN5I_GPIO_OUTPUT);
- *(volatile unsigned int*)(mmap_Base + PIO_PG_CFG1_OFFSET) = (1<<4);
- rtapi_print("SUN5I_GPIO: Set up hal_pin_bit_newf()\n");
- if ((retval = hal_pin_bit_newf(HAL_IN, &port_data[9], comp_id, "sun5i_gpio.pin-%02d-out", 9)) < 0)
- if (retval < 0) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: ERROR: pin %d export failed with err=%i\n", n,retval);
- hal_exit(comp_id);
- return -1;
- }
- rtapi_print("SUN5I_GPIO: Set up hal_export_funct()\n");
- retval = hal_export_funct("sun5i_gpio.write", write_port, 0, 0, 0, comp_id);
- if (retval < 0) {
- rtapi_print_msg(RTAPI_MSG_ERR, "SUN5I_GPIO: ERROR: write funct export failed\n");
- hal_exit(comp_id);
- return -1;
- }
- hal_ready(comp_id);
- rtapi_print("SUN5I_GPIO: installed driver\n");
- return 0;
- }
- void rtapi_app_exit(void)
- {
- //iounmap(GADDR);
- hal_exit(comp_id);
- }
- static void write_port(void *arg, long period)
- {
- //rtapi_print("SUN5I_GPIO: port_data[9] = %i\n", (int)*port_data[9]);
- if (*(port_data[9])) {
- *(volatile unsigned int*)(mmap_Base + PIO_PG_DATA_OFFSET) = (1<<9);
- } else {
- *(volatile unsigned int*)(mmap_Base + PIO_PG_DATA_OFFSET) = (0<<9);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement