summaryrefslogtreecommitdiff
path: root/common/fdt_decode.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2011-06-16 13:08:57 -0700
committerSimon Glass <sjg@chromium.org>2011-08-29 10:39:35 -0700
commit940709f104efe92cdd383751ca8b81ccc8e41da2 (patch)
tree258141c7c1c53f09ef234d7e64fc70d5b187e550 /common/fdt_decode.c
parentea1e225fb9a6a0dbd5a810a1de711e308bc4b175 (diff)
fdt: Refactor GPIO support a little
This adds support for a single GPIO as well as a list. The GPIO flags cell is now used, where the bits are defined as: Bit Meaning ===================== 0 GPIO is an output (1=output, 0=input) 1 Value to set if an output (1=high, 0=low) BUG=chromium-os:11623 TEST=build and boot on Seaboard Change-Id: I7084f3cbac9c33fe592ebf39332593b9a4631425 Reviewed-on: http://gerrit.chromium.org/gerrit/2779 Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common/fdt_decode.c')
-rw-r--r--common/fdt_decode.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/common/fdt_decode.c b/common/fdt_decode.c
index 670fa1687b..049646cad8 100644
--- a/common/fdt_decode.c
+++ b/common/fdt_decode.c
@@ -314,16 +314,17 @@ int fdt_decode_get_spi_switch(const void *blob, struct fdt_spi_uart *config)
}
/**
- * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with the
- * last one being GPIO_NONE
+ * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with no
+ * terminating item.
*
* @param blob FDT blob to use
* @param node Node to look at
* @param property Node property name
- * @param gpio Array of gpio elements to fill from FDT
+ * @param gpio Array of gpio elements to fill from FDT. This will be
+ * untouched if either 0 or an error is returned
* @param max_count Maximum number of elements allowed
- * @return 0 if ok, -FDT_ERR_BADLAYOUT if max_count would be exceeded, or
- * -FDT_ERR_MISSING if the property is missing.
+ * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would
+ * be exceeded, or -FDT_ERR_MISSING if the property is missing.
*/
static int decode_gpios(const void *blob, int node, const char *property,
struct fdt_gpio_state *gpio, int max_count)
@@ -331,25 +332,60 @@ static int decode_gpios(const void *blob, int node, const char *property,
const u32 *cell;
int len, i;
+ assert(max_count > 0);
cell = fdt_getprop(blob, node, property, &len);
if (!cell)
return -FDT_ERR_MISSING;
len /= sizeof(u32) * 3; /* 3 cells per GPIO record */
- if (len >= max_count) {
- printf("FDT: decode_gpios: too many GPIOs\n");
+ if (len > max_count) {
+ printf("FDT: decode_gpios: too many GPIOs / cells for "
+ "property '%s'\n", property);
return -FDT_ERR_BADLAYOUT;
}
for (i = 0; i < len; i++, cell += 3) {
gpio[i].gpio = fdt32_to_cpu(cell[1]);
- gpio[i].high = fdt32_to_cpu(cell[2]);
+ gpio[i].flags = fdt32_to_cpu(cell[2]);
}
+ return len;
+}
+
+/**
+ * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with the
+ * last one being GPIO_NONE.
+ *
+ * @param blob FDT blob to use
+ * @param node Node to look at
+ * @param property Node property name
+ * @param gpio Array of gpio elements to fill from FDT
+ * @param max_count Maximum number of elements allowed, including the
+ * terminator
+ * @return 0 if ok, -FDT_ERR_BADLAYOUT if max_count would be exceeded, or
+ * -FDT_ERR_MISSING if the property is missing.
+ */
+static int decode_gpio_list(const void *blob, int node, const char *property,
+ struct fdt_gpio_state *gpio, int max_count)
+{
+ int err = decode_gpios(blob, node, property, gpio, max_count - 1);
/* terminate the list */
- gpio[len].gpio = FDT_GPIO_NONE;
+ if (err < 0)
+ return err;
+ gpio[err].gpio = FDT_GPIO_NONE;
return 0;
}
+void fdt_setup_gpio(struct fdt_gpio_state *gpio)
+{
+ if (!fdt_gpio_isvalid(gpio))
+ return;
+
+ if (gpio->flags & FDT_GPIO_OUTPUT)
+ gpio_direction_output(gpio->gpio, gpio->flags & FDT_GPIO_HIGH);
+ else
+ gpio_direction_input(gpio->gpio);
+}
+
void fdt_setup_gpios(struct fdt_gpio_state *gpio_list)
{
struct fdt_gpio_state *gpio;
@@ -361,11 +397,15 @@ void fdt_setup_gpios(struct fdt_gpio_state *gpio_list)
printf("FDT: fdt_setup_gpios: too many GPIOs\n");
return;
}
- gpio_direction_output(gpio->gpio, 1);
- gpio_set_value(gpio->gpio, gpio->high);
+ fdt_setup_gpio(gpio);
}
}
+int fdt_get_gpio_num(struct fdt_gpio_state *gpio)
+{
+ return fdt_gpio_isvalid(gpio) ? gpio->gpio : -1;
+}
+
int fdt_decode_lcd(const void *blob, struct fdt_lcd *config)
{
int node, err, bpp, bit;
@@ -404,7 +444,8 @@ int fdt_decode_lcd(const void *blob, struct fdt_lcd *config)
!config->pwfm || !config->disp)
return -FDT_ERR_MISSING;
config->frame_buffer = get_addr(blob, node, "frame-buffer");
- return decode_gpios(blob, node, "gpios", config->gpios, FDT_LCD_GPIOS);
+ return decode_gpio_list(blob, node, "gpios", config->gpios,
+ FDT_LCD_GPIOS);
}
int fdt_decode_usb(const void *blob, int node, unsigned osc_frequency_mhz,