[Skiboot] [PATCH v2 3/7] external/common: Create common code for initialising libflash components
Cyril Bur
cyril.bur at au1.ibm.com
Mon Aug 24 16:08:23 AEST 2015
In order to access the flash on ARM (presumably code running on a BMC), the
hardware is involved. In order to access the flash on POWER (presumably
code running on a host), opal calls through the Linux MTD driver are
involved. In order to access the flash on x86 (presumably on a
developer/admin system), you can't but it would be nice to be able to
manipulate data which has come from the flash or will go onto the flash.
The pflash and the gard tool both can read and write to the 'flash' and
with the introduction of the blocklevel interface the details of how the
flash is read from and written to is sufficiently abstracted that these
tools don't need to know what they're running on.
What does differ is the setup, and not by too much either. This common code
pulls out the setup of the flash hardware on ARM, the searching for the
appropriate MTD device on power and generic blocklevel device init for all
three architectures.
Signed-off-by: Cyril Bur <cyril.bur at au1.ibm.com>
---
external/common/arch_flash.h | 41 +++
external/common/arch_flash_arm.c | 294 +++++++++++++++++++++
.../{pflash/io.h => common/arch_flash_arm_io.h} | 43 +--
external/common/arch_flash_common.c | 38 +++
external/pflash/Makefile | 2 +
external/pflash/arm_io.c | 139 ----------
external/pflash/pflash.c | 170 +++---------
external/pflash/rules.mk | 11 +-
libflash/libflash.c | 8 +
libflash/libflash.h | 5 +
10 files changed, 436 insertions(+), 315 deletions(-)
create mode 100644 external/common/arch_flash.h
create mode 100644 external/common/arch_flash_arm.c
rename external/{pflash/io.h => common/arch_flash_arm_io.h} (60%)
create mode 100644 external/common/arch_flash_common.c
delete mode 100644 external/pflash/arm_io.c
diff --git a/external/common/arch_flash.h b/external/common/arch_flash.h
new file mode 100644
index 0000000..60c4de8
--- /dev/null
+++ b/external/common/arch_flash.h
@@ -0,0 +1,41 @@
+/* Copyright 2015 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __EXTERNAL_ARCH_FLASH_H
+#define __EXTERNAL_ARCH_FLASH_H
+
+#include <getopt.h>
+#include <libflash/blocklevel.h>
+
+int arch_flash_init(struct blocklevel_device **bl, const char *file);
+
+void arch_flash_close(struct blocklevel_device *bl, const char *file);
+
+/* Low level functions that an architecture may support */
+
+/*
+ * If called BEFORE init, then the behaviour is to set that on init the BMC
+ * flash will be opened.
+ * If called AFTER init, then the behaviour is to return wether or not BMC
+ * flash has been opened
+ */
+int arch_flash_bmc(struct blocklevel_device *bl, int bmc);
+
+int arch_flash_erase_chip(struct blocklevel_device *bl);
+int arch_flash_4b_mode(struct blocklevel_device *bl, int set_4b);
+int arch_flash_set_wrprotect(struct blocklevel_device *bl, int set);
+
+#endif /* __EXTERNAL_ARCH_FLASH_H */
diff --git a/external/common/arch_flash_arm.c b/external/common/arch_flash_arm.c
new file mode 100644
index 0000000..b3c9454
--- /dev/null
+++ b/external/common/arch_flash_arm.c
@@ -0,0 +1,294 @@
+/* Copyright 2015 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+
+#include <ccan/container_of/container_of.h>
+
+#include <libflash/libflash.h>
+#include <libflash/file.h>
+#include "ast.h"
+#include "arch_flash.h"
+
+struct flash_chip;
+
+static struct arch_arm_data {
+ int fd;
+ void *ahb_reg_map;
+ void *gpio_ctrl;
+ size_t ahb_flash_base;
+ size_t ahb_flash_size;
+ void *ahb_flash_map;
+ int bmc;
+ struct flash_chip *flash_chip;
+ struct blocklevel_device *init_bl;
+} arch_data;
+
+uint32_t ast_ahb_readl(uint32_t offset)
+{
+ assert(((offset ^ AHB_REGS_BASE) & ~(AHB_REGS_SIZE - 1)) == 0);
+
+ return readl(arch_data.ahb_reg_map + (offset - AHB_REGS_BASE));
+}
+
+void ast_ahb_writel(uint32_t val, uint32_t offset)
+{
+ assert(((offset ^ AHB_REGS_BASE) & ~(AHB_REGS_SIZE - 1)) == 0);
+
+ writel(val, arch_data.ahb_reg_map + (offset - AHB_REGS_BASE));
+}
+
+int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len)
+{
+ if (reg < arch_data.ahb_flash_base ||
+ (reg + len) > (arch_data.ahb_flash_base + arch_data.ahb_flash_size))
+ return -1;
+ reg -= arch_data.ahb_flash_base;
+
+ if (((reg | (unsigned long)src | len) & 3) == 0) {
+ while(len > 3) {
+ uint32_t val = *(uint32_t *)src;
+ writel(val, arch_data.ahb_flash_map + reg);
+ src += 4;
+ reg += 4;
+ len -= 4;
+ }
+ }
+
+ while(len--) {
+ uint8_t val = *(uint8_t *)src;
+ writeb(val, arch_data.ahb_flash_map + reg++);
+ src += 1;
+ }
+ return 0;
+}
+
+/*
+ * GPIO stuff to be replaced by higher level accessors for
+ * controlling the flash write lock via sysfs
+ */
+
+static inline uint32_t gpio_ctl_readl(uint32_t offset)
+{
+ return readl(arch_data.gpio_ctrl + offset);
+}
+
+static inline void gpio_ctl_writel(uint32_t val, uint32_t offset)
+{
+ writel(val, arch_data.gpio_ctrl + offset);
+}
+
+static bool set_wrprotect(bool protect)
+{
+ uint32_t reg;
+ bool was_protected;
+
+ reg = gpio_ctl_readl(0x20);
+ was_protected = !!(reg & 0x00004000);
+ if (protect)
+ reg |= 0x00004000; /* GPIOF[6] value */
+ else
+ reg &= ~0x00004000; /* GPIOF[6] value */
+ gpio_ctl_writel(reg, 0x20);
+ reg = gpio_ctl_readl(0x24);
+ reg |= 0x00004000; /* GPIOF[6] direction */
+ gpio_ctl_writel(reg, 0x24);
+
+ return was_protected;
+}
+
+int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len)
+{
+ if (reg < arch_data.ahb_flash_base ||
+ (reg + len) > (arch_data.ahb_flash_base + arch_data.ahb_flash_size))
+ return -1;
+ reg -= arch_data.ahb_flash_base;
+
+ if (((reg | (unsigned long)dst | len) & 3) == 0) {
+ while(len > 3) {
+ *(uint32_t *)dst = readl(arch_data.ahb_flash_map + reg);
+ dst += 4;
+ reg += 4;
+ len -= 4;
+ }
+ }
+
+ while(len--) {
+ *(uint8_t *)dst = readb(arch_data.ahb_flash_map + reg++);
+ dst += 1;
+ }
+ return 0;
+}
+
+static void close_devs(void)
+{
+ /*
+ * Old code doesn't do this, not sure why not
+ *
+ * munmap(arch_data.ahb_flash_map, arch_data.ahb_flash_size);
+ * munmap(arch_data.gpio_ctrl, GPIO_CTRL_SIZE);
+ * munmap(arch_data.ahb_reg_map, AHB_REGS_SIZE);
+ * close(arch_data.fd);
+ */
+}
+
+static int open_devs(int bmc)
+{
+ arch_data.fd = open("/dev/mem", O_RDWR | O_SYNC);
+ if (arch_data.fd < 0) {
+ perror("can't open /dev/mem");
+ return -1;
+ }
+
+ arch_data.ahb_reg_map = mmap(0, AHB_REGS_SIZE, PROT_READ | PROT_WRITE,
+ MAP_SHARED, arch_data.fd, AHB_REGS_BASE);
+ if (arch_data.ahb_reg_map == MAP_FAILED) {
+ perror("can't map AHB registers /dev/mem");
+ return -1;
+ }
+ arch_data.gpio_ctrl = mmap(0, GPIO_CTRL_SIZE, PROT_READ | PROT_WRITE,
+ MAP_SHARED, arch_data.fd, GPIO_CTRL_BASE);
+ if (arch_data.gpio_ctrl == MAP_FAILED) {
+ perror("can't map GPIO control via /dev/mem");
+ return -1;
+ }
+ arch_data.ahb_flash_base = bmc ? BMC_FLASH_BASE : PNOR_FLASH_BASE;
+ arch_data.ahb_flash_size = bmc ? BMC_FLASH_SIZE : PNOR_FLASH_SIZE;
+ arch_data.ahb_flash_map = mmap(0, arch_data.ahb_flash_size, PROT_READ |
+ PROT_WRITE, MAP_SHARED, arch_data.fd, arch_data.ahb_flash_base);
+ if (arch_data.ahb_flash_map == MAP_FAILED) {
+ perror("can't map flash via /dev/mem");
+ return -1;
+ }
+ return 0;
+}
+
+static struct blocklevel_device *flash_setup(int bmc)
+{
+ int rc;
+ struct blocklevel_device *bl;
+ struct spi_flash_ctrl *fl;
+
+ /* Open and map devices */
+ open_devs(bmc);
+
+ /* Create the AST flash controller */
+ rc = ast_sf_open(bmc ? AST_SF_TYPE_BMC : AST_SF_TYPE_PNOR, &fl);
+ if (rc) {
+ fprintf(stderr, "Failed to open controller\n");
+ return NULL;
+ }
+
+ /* Open flash chip */
+ rc = flash_init(fl, &bl, &arch_data.flash_chip);
+ if (rc) {
+ fprintf(stderr, "Failed to open flash chip\n");
+ return NULL;
+ }
+
+ return bl;
+}
+
+int arch_flash_bmc(struct blocklevel_device *bl, int bmc)
+{
+ if (!arch_data.init_bl) {
+ arch_data.bmc = bmc;
+ return 0;
+ }
+
+ /* Called with a BL not inited here, bail */
+ if (arch_data.init_bl != bl)
+ return -1;
+
+ return arch_data.flash_chip ? arch_data.bmc : -1;
+}
+
+int arch_flash_erase_chip(struct blocklevel_device *bl)
+{
+ /* Called with a BL not inited here, bail */
+ if (!arch_data.init_bl || arch_data.init_bl != bl)
+ return -1;
+
+ if (!arch_data.flash_chip)
+ return -1;
+
+ return flash_erase_chip(arch_data.flash_chip);
+}
+
+int arch_flash_4b_mode(struct blocklevel_device *bl, int set_4b)
+{
+ /* Called with a BL not inited here, bail */
+ if (!arch_data.init_bl || arch_data.init_bl != bl)
+ return -1;
+
+ if (!arch_data.flash_chip)
+ return -1;
+
+ return flash_force_4b_mode(arch_data.flash_chip, set_4b);
+}
+
+int arch_flash_set_wrprotect(struct blocklevel_device *bl, int set)
+{
+ /* Called with a BL not inited here, bail */
+ if (!arch_data.init_bl || arch_data.init_bl != bl)
+ return -1;
+
+ if (!arch_data.flash_chip)
+ return -1;
+
+ return set_wrprotect(set);
+}
+
+int arch_flash_init(struct blocklevel_device **r_bl, const char *file)
+{
+ struct blocklevel_device *new_bl;
+
+ /* Check we haven't already inited */
+ if (arch_data.init_bl)
+ return -1;
+
+ if (file) {
+ file_init_path(file, NULL, &new_bl);
+ } else {
+ new_bl = flash_setup(arch_data.bmc);
+ }
+ if (!new_bl)
+ return -1;
+
+ arch_data.init_bl = new_bl;
+ *r_bl = new_bl;
+ return 0;
+}
+
+void arch_flash_close(struct blocklevel_device *bl, const char *file)
+{
+ if (file) {
+ file_exit_close(bl);
+ } else {
+ flash_exit_close(bl, &ast_sf_close);
+ close_devs();
+ }
+}
diff --git a/external/pflash/io.h b/external/common/arch_flash_arm_io.h
similarity index 60%
rename from external/pflash/io.h
rename to external/common/arch_flash_arm_io.h
index 257cfd2..a1ee1f3 100644
--- a/external/pflash/io.h
+++ b/external/common/arch_flash_arm_io.h
@@ -27,29 +27,6 @@
#define LPC_FLASH_BASE 0x0e000000
#define LPC_CTRL_BASE 0x1e789000
-extern void open_devs(bool use_lpc, bool bmc_flash);
-extern bool set_wrprotect(bool protect);
-
-#ifdef __powerpc__
-
-extern void close_devs(void);
-
-/* AST access functions */
-extern uint32_t (*ast_ahb_readl)(uint32_t offset);
-extern void (*ast_ahb_writel)(uint32_t val, uint32_t offset);
-extern int (*ast_copy_to_ahb)(uint32_t reg, const void *src, uint32_t len);
-extern int (*ast_copy_from_ahb)(void *dst, uint32_t reg, uint32_t len);
-
-/* SFC LPC access functions (big endian) */
-extern int lpc_fw_write32(uint32_t val, uint32_t addr);
-extern int lpc_fw_read32(uint32_t *val, uint32_t addr);
-
-extern void check_platform(bool *has_sfc, bool *has_ast);
-
-#else
-
-static inline void close_devs(void) { }
-
static inline uint8_t readb(void *addr)
{
asm volatile("" : : : "memory");
@@ -90,22 +67,8 @@ static inline void writel(uint32_t val, void *addr)
* AHB register and flash access
*/
-extern void *ahb_reg_map;
-
-static inline uint32_t ast_ahb_readl(uint32_t offset)
-{
- assert(((offset ^ AHB_REGS_BASE) & ~(AHB_REGS_SIZE - 1)) == 0);
-
- return readl(ahb_reg_map + (offset - AHB_REGS_BASE));
-}
-
-static inline void ast_ahb_writel(uint32_t val, uint32_t offset)
-{
- assert(((offset ^ AHB_REGS_BASE) & ~(AHB_REGS_SIZE - 1)) == 0);
-
- writel(val, ahb_reg_map + (offset - AHB_REGS_BASE));
-}
-
+extern uint32_t ast_ahb_readl(uint32_t offset);
+extern void ast_ahb_writel(uint32_t val, uint32_t offset);
extern int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len);
extern int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len);
@@ -115,7 +78,5 @@ static inline void check_platform(bool *has_sfc, bool *has_ast)
*has_ast = true;
}
-#endif
-
#endif /* __IO_H */
diff --git a/external/common/arch_flash_common.c b/external/common/arch_flash_common.c
new file mode 100644
index 0000000..ef4669a
--- /dev/null
+++ b/external/common/arch_flash_common.c
@@ -0,0 +1,38 @@
+/* Copyright 2015 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libflash/blocklevel.h>
+
+/* Default implmentations */
+int __attribute__((weak)) arch_flash_erase_chip(struct blocklevel_device *bl)
+{
+ return -1;
+}
+
+int __attribute__((weak)) arch_flash_4b_mode(struct blocklevel_device *bl, int set_4b)
+{
+ return -1;
+}
+
+int __attribute__((weak)) arch_flash_bmc(struct blocklevel_device *bl, int bmc)
+{
+ return -1;
+}
+
+int __attribute__((weak)) arch_flash_set_wrprotect(struct blocklevel_device *bl, int set)
+{
+ return -1;
+}
diff --git a/external/pflash/Makefile b/external/pflash/Makefile
index 44cbe7b..45f500b 100644
--- a/external/pflash/Makefile
+++ b/external/pflash/Makefile
@@ -19,6 +19,8 @@ ast-sf-ctrl.c:
make_version.sh:
ln -sf ../../make_version.sh
+ ln -sf ../../external/common .
+ ln -sf ../../external/common/arch_flash_$(arch)_io.h io.h
$(OBJS) : links
diff --git a/external/pflash/arm_io.c b/external/pflash/arm_io.c
deleted file mode 100644
index ad040c3..0000000
--- a/external/pflash/arm_io.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <byteswap.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <getopt.h>
-#include <limits.h>
-#include <arpa/inet.h>
-#include <assert.h>
-
-#include "io.h"
-
-void *ahb_reg_map;
-void *ahb_flash_map;
-uint32_t ahb_flash_base, ahb_flash_size;
-void *gpio_ctrl;
-
-int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len)
-{
- if (reg < ahb_flash_base ||
- (reg + len) > (ahb_flash_base + ahb_flash_size))
- return -1;
- reg -= ahb_flash_base;
-
- if (((reg | (unsigned long)src | len) & 3) == 0) {
- while(len > 3) {
- uint32_t val = *(uint32_t *)src;
- writel(val, ahb_flash_map + reg);
- src += 4;
- reg += 4;
- len -= 4;
- }
- }
-
- while(len--) {
- uint8_t val = *(uint8_t *)src;
- writeb(val, ahb_flash_map + reg++);
- src += 1;
- }
- return 0;
-}
-
-
-int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len)
-{
- if (reg < ahb_flash_base ||
- (reg + len) > (ahb_flash_base + ahb_flash_size))
- return -1;
- reg -= ahb_flash_base;
-
- if (((reg | (unsigned long)dst | len) & 3) == 0) {
- while(len > 3) {
- *(uint32_t *)dst = readl(ahb_flash_map + reg);
- dst += 4;
- reg += 4;
- len -= 4;
- }
- }
-
- while(len--) {
- *(uint8_t *)dst = readb(ahb_flash_map + reg++);
- dst += 1;
- }
- return 0;
-}
-
-/*
- * GPIO stuff to be replaced by higher level accessors for
- * controlling the flash write lock via sysfs
- */
-
-static inline uint32_t gpio_ctl_readl(uint32_t offset)
-{
- return readl(gpio_ctrl + offset);
-}
-
-static inline void gpio_ctl_writel(uint32_t val, uint32_t offset)
-{
- writel(val, gpio_ctrl + offset);
-}
-
-
-bool set_wrprotect(bool protect)
-{
- uint32_t reg;
- bool was_protected;
-
- reg = gpio_ctl_readl(0x20);
- was_protected = !!(reg & 0x00004000);
- if (protect)
- reg |= 0x00004000; /* GPIOF[6] value */
- else
- reg &= ~0x00004000; /* GPIOF[6] value */
- gpio_ctl_writel(reg, 0x20);
- reg = gpio_ctl_readl(0x24);
- reg |= 0x00004000; /* GPIOF[6] direction */
- gpio_ctl_writel(reg, 0x24);
-
- return was_protected;
-}
-
-void open_devs(bool use_lpc, bool bmc_flash)
-{
- int fd;
-
- (void)use_lpc;
-
- fd = open("/dev/mem", O_RDWR | O_SYNC);
- if (fd < 0) {
- perror("can't open /dev/mem");
- exit(1);
- }
- ahb_reg_map = mmap(0, AHB_REGS_SIZE, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, AHB_REGS_BASE);
- if (ahb_reg_map == MAP_FAILED) {
- perror("can't map AHB registers /dev/mem");
- exit(1);
- }
- gpio_ctrl = mmap(0, GPIO_CTRL_SIZE, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, GPIO_CTRL_BASE);
- if (gpio_ctrl == MAP_FAILED) {
- perror("can't map GPIO control via /dev/mem");
- exit(1);
- }
- ahb_flash_base = bmc_flash ? BMC_FLASH_BASE : PNOR_FLASH_BASE;
- ahb_flash_size = bmc_flash ? BMC_FLASH_SIZE : PNOR_FLASH_SIZE;
- ahb_flash_map = mmap(0, ahb_flash_size, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, ahb_flash_base);
- if (ahb_flash_map == MAP_FAILED) {
- perror("can't map flash via /dev/mem");
- exit(1);
- }
-}
diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c
index 0d2d669..9deef1c 100644
--- a/external/pflash/pflash.c
+++ b/external/pflash/pflash.c
@@ -17,10 +17,10 @@
#include <libflash/libflash.h>
#include <libflash/libffs.h>
#include <libflash/blocklevel.h>
+#include <common/arch_flash.h>
#include "progress.h"
#include "io.h"
#include "ast.h"
-#include "sfc-ctrl.h"
#define __aligned(x) __attribute__((aligned(x)))
@@ -29,19 +29,15 @@ extern const char version[];
static bool must_confirm = true;
static bool dummy_run;
-static bool need_relock;
+static int need_relock;
static bool bmc_flash;
static uint32_t ffs_toc = 0;
static int flash_side = 0;
-#ifdef __powerpc__
-static bool using_sfc;
-#endif
#define FILE_BUF_SIZE 0x10000
static uint8_t file_buf[FILE_BUF_SIZE] __aligned(0x1000);
static struct blocklevel_device *bl;
-static struct spi_flash_ctrl *fl_ctrl;
static struct ffs_handle *ffsh;
static uint32_t fl_total_size, fl_erase_granule;
static const char *fl_name;
@@ -211,7 +207,7 @@ static void erase_chip(void)
return;
}
- rc = flash_erase_chip(bl);
+ rc = arch_flash_erase_chip(bl);
if (rc) {
fprintf(stderr, "Error %d erasing chip\n", rc);
exit(1);
@@ -390,9 +386,13 @@ static void enable_4B_addresses(void)
printf("Switching to 4-bytes address mode\n");
- rc = flash_force_4b_mode(bl, true);
+ rc = arch_flash_4b_mode(bl, true);
if (rc) {
- fprintf(stderr, "Error %d enabling 4b mode\n", rc);
+ if (rc == -1) {
+ fprintf(stderr, "Switching address mode not availible on this architecture\n");
+ } else {
+ fprintf(stderr, "Error %d enabling 4b mode\n", rc);
+ }
exit(1);
}
}
@@ -403,108 +403,15 @@ static void disable_4B_addresses(void)
printf("Switching to 3-bytes address mode\n");
- rc = flash_force_4b_mode(bl, false);
- if (rc) {
- fprintf(stderr, "Error %d disabling 4b mode\n", rc);
- exit(1);
- }
-}
-
-static void flash_access_cleanup_bmc(void)
-{
- if (ffsh)
- ffs_close(ffsh);
- flash_exit(bl);
- ast_sf_close(fl_ctrl);
- close_devs();
-}
-
-static void flash_access_setup_bmc(bool use_lpc, bool need_write)
-{
- int rc;
-
- /* Open and map devices */
- open_devs(use_lpc, true);
-
- /* Create the AST flash controller */
- rc = ast_sf_open(AST_SF_TYPE_BMC, &fl_ctrl);
+ rc = arch_flash_4b_mode(bl, false);
if (rc) {
- fprintf(stderr, "Failed to open controller\n");
- exit(1);
- }
-
- /* Open flash chip */
- rc = flash_init(fl_ctrl, &bl);
- if (rc) {
- fprintf(stderr, "Failed to open flash chip\n");
- exit(1);
- }
-
- /* Setup cleanup function */
- atexit(flash_access_cleanup_bmc);
-}
-
-static void flash_access_cleanup_pnor(void)
-{
- /* Re-lock flash */
- if (need_relock)
- set_wrprotect(true);
-
- if (ffsh)
- ffs_close(ffsh);
- flash_exit(bl);
-#ifdef __powerpc__
- if (using_sfc)
- sfc_close(fl_ctrl);
- else
- ast_sf_close(fl_ctrl);
-#else
- ast_sf_close(fl_ctrl);
-#endif
- close_devs();
-}
-
-static void flash_access_setup_pnor(bool use_lpc, bool use_sfc, bool need_write)
-{
- int rc;
-
- /* Open and map devices */
- open_devs(use_lpc, false);
-
-#ifdef __powerpc__
- if (use_sfc) {
- /* Create the SFC flash controller */
- rc = sfc_open(&fl_ctrl);
- if (rc) {
- fprintf(stderr, "Failed to open controller\n");
- exit(1);
- }
- using_sfc = true;
- } else {
-#endif
- /* Create the AST flash controller */
- rc = ast_sf_open(AST_SF_TYPE_PNOR, &fl_ctrl);
- if (rc) {
- fprintf(stderr, "Failed to open controller\n");
- exit(1);
+ if (rc == -1) {
+ fprintf(stderr, "Switching address mode not availible on this architecture\n");
+ } else {
+ fprintf(stderr, "Error %d enabling 4b mode\n", rc);
}
-#ifdef __powerpc__
- }
-#endif
-
- /* Open flash chip */
- rc = flash_init(fl_ctrl, &bl);
- if (rc) {
- fprintf(stderr, "Failed to open flash chip\n");
exit(1);
}
-
- /* Unlock flash (PNOR only) */
- if (need_write)
- need_relock = set_wrprotect(false);
-
- /* Setup cleanup function */
- atexit(flash_access_cleanup_pnor);
}
static void print_version(void)
@@ -583,6 +490,13 @@ static void print_help(const char *pname)
printf("\t\tThis message.\n\n");
}
+void exiting(int d, void *p)
+{
+ if (need_relock)
+ arch_flash_set_wrprotect(bl, 1);
+ arch_flash_close(bl, NULL);
+}
+
int main(int argc, char *argv[])
{
const char *pname = argv[0];
@@ -590,9 +504,8 @@ int main(int argc, char *argv[])
uint32_t erase_start = 0, erase_size = 0;
bool erase = false, do_clear = false;
bool program = false, erase_all = false, info = false, do_read = false;
- bool enable_4B = false, disable_4B = false, use_lpc = true;
+ bool enable_4B = false, disable_4B = false;
bool show_help = false, show_version = false;
- bool has_sfc = false, has_ast = false;
bool no_action = false, tune = false;
char *write_file = NULL, *read_file = NULL, *part_name = NULL;
bool ffs_toc_seen = false;
@@ -603,7 +516,6 @@ int main(int argc, char *argv[])
{"address", required_argument, NULL, 'a'},
{"size", required_argument, NULL, 's'},
{"partition", required_argument, NULL, 'P'},
- {"lpc", no_argument, NULL, 'l'},
{"bmc", no_argument, NULL, 'b'},
{"enable-4B", no_argument, NULL, '4'},
{"disable-4B", no_argument, NULL, '3'},
@@ -624,7 +536,7 @@ int main(int argc, char *argv[])
};
int c, oidx = 0;
- c = getopt_long(argc, argv, "a:s:P:r:43Eep:fdihlvbtgS:T:c",
+ c = getopt_long(argc, argv, "a:s:P:r:43Eep:fdihvbtgS:T:c",
long_opts, &oidx);
if (c == EOF)
break;
@@ -668,9 +580,6 @@ int main(int argc, char *argv[])
case 'i':
info = true;
break;
- case 'l':
- use_lpc = true;
- break;
case 'b':
bmc_flash = true;
break;
@@ -791,24 +700,19 @@ int main(int argc, char *argv[])
write_size = stbuf.st_size;
}
- /* Check platform */
- check_platform(&has_sfc, &has_ast);
-
- /* Prepare for access */
if (bmc_flash) {
- if (!has_ast) {
- fprintf(stderr, "No BMC on this platform\n");
- exit(1);
- }
- flash_access_setup_bmc(use_lpc, erase || program);
- } else {
- if (!has_ast && !has_sfc) {
- fprintf(stderr, "No BMC nor SFC on this platform\n");
+ if (arch_flash_bmc(NULL, 1) == -1) {
+ fprintf(stderr, "Can't switch to BMC flash on this architecture\n");
exit(1);
}
- flash_access_setup_pnor(use_lpc, has_sfc, erase || program);
}
+ if (arch_flash_init(&bl, NULL))
+ exit(1);
+
+ on_exit(exiting, NULL);
+
+
rc = blocklevel_get_info(bl, &fl_name,
&fl_total_size, &fl_erase_granule);
if (rc) {
@@ -898,7 +802,7 @@ int main(int argc, char *argv[])
enable_4B_addresses();
if (disable_4B)
disable_4B_addresses();
- if (info ) {
+ if (info) {
/*
* Don't pass through modfied TOC value if the modification was done
* because of --size, but still respect if it came from --toc (we
@@ -906,6 +810,16 @@ int main(int argc, char *argv[])
*/
print_flash_info(flash_side ? 0 : ffs_toc);
}
+
+ /* Unlock flash (PNOR only) */
+ if ((erase || program || do_clear) && !bmc_flash) {
+ need_relock = arch_flash_set_wrprotect(bl, false);
+ if (need_relock == -1) {
+ fprintf(stderr, "Architecture doesn't support write protection on flash\n");
+ need_relock = 0;
+ exit (1);
+ }
+ }
if (do_read)
do_read_file(read_file, address, read_size);
if (erase_all)
diff --git a/external/pflash/rules.mk b/external/pflash/rules.mk
index d89748b..8cd8c73 100644
--- a/external/pflash/rules.mk
+++ b/external/pflash/rules.mk
@@ -1,21 +1,18 @@
ARCH=$(shell ./get_arch.sh "$(CROSS_COMPILE)")
-ifeq ($(ARCH),ARCH_POWERPC)
-ARCH_OBJS = powerpc_io.o sfc-ctrl.o
-else
ifeq ($(ARCH),ARCH_ARM)
-ARCH_OBJS = arm_io.o
+arch = arm
+ARCH_OBJS = common/arch_flash_common.o common/arch_flash_arm.o ast-sf-ctrl.o
else
$(error Unsupported architecture $(ARCH))
endif
-endif
.DEFAULT_GOAL := all
CFLAGS = -O2 -Wall -I.
LDFLAGS = -lrt
-OBJS = pflash.o progress.o ast-sf-ctrl.o version.o
-OBJS += libflash/libflash.o libflash/libffs.o libflash/ecc.o libflash/blocklevel.o
+OBJS = pflash.o progress.o version.o
+OBJS += libflash/libflash.o libflash/libffs.o libflash/ecc.o libflash/blocklevel.o libflash/file.o
OBJS += $(ARCH_OBJS)
EXE = pflash
diff --git a/libflash/libflash.c b/libflash/libflash.c
index 18357fb..c43f212 100644
--- a/libflash/libflash.c
+++ b/libflash/libflash.c
@@ -854,3 +854,11 @@ void flash_exit(struct blocklevel_device *bl)
free(container_of(bl, struct flash_chip, bl));
}
+void flash_exit_close(struct blocklevel_device *bl, void (*close)(struct spi_flash_ctrl *ctrl))
+{
+ if (bl) {
+ struct flash_chip *c = container_of(bl, struct flash_chip, bl);
+ close(c->ctrl);
+ free(c);
+ }
+}
diff --git a/libflash/libflash.h b/libflash/libflash.h
index 82b38ca..4fecfe7 100644
--- a/libflash/libflash.h
+++ b/libflash/libflash.h
@@ -49,6 +49,11 @@ int flash_init(struct spi_flash_ctrl *ctrl, struct blocklevel_device **bl,
struct flash_chip **flash_chip);
void flash_exit(struct blocklevel_device *bl);
+/*
+ * Function which till call close on the underlying struct spi_flash_ctrl
+ */
+void flash_exit_close(struct blocklevel_device *bl, void (*close)(struct spi_flash_ctrl *ctrl));
+
/* libflash sets the 4b mode automatically based on the flash
* size and controller capabilities but it can be overriden
*/
--
2.5.0
More information about the Skiboot
mailing list